记一次数据库“脑裂“问题的复盘
Posted 鱼翔空
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次数据库“脑裂“问题的复盘相关的知识,希望对你有一定的参考价值。
问题回顾
-
4月2日 开发发现专有云的用户rds实例链接数报警,并于中午发起了数据库配置变更申请;
-
4月8日14:00 某云在场运维巡检,发现该实例有中断的任务,尝试补偿执行失败;
-
4月8日14:23 某云在场运维直接手动操作跳过一些步骤,将中断任务继续执行;
-
4月8日17:30,许久没消息的报警群,突然收到一堆报警,用户系统提示:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException,其他系统提示调用用户系统Read timed out,后续又报Connection refused
-
4月8日17:35 开发在堡垒机上尝试连接数据库,发现无法telnet通
-
4月8日17:36 上升到DBA,发现该实例在已经不存在;
-
4月8日17:40 上升到某云,在场运维排查后无法解决;
-
4月8日17:50 开始呼叫总部支持;
-
4月8日18:00 发现rds对应的vip后续无挂载实例;
-
4月8日18:05 通过元数据发现对应的主实例;
-
尝试通过应用程序挂载主实例,多次尝试失败;
-
4月8日18:25 某云内部沟通,让运维直接手动操作,挂载成功;
-
4月8日18:29 数据库连接恢复,应用恢复正常;
-
4月8日18:35 验证整体流程没问题;
-
4月9日10:00 安排开发对数据进行抽样排查;
-
4月9日10:15 测试发现从库从4月8日14:23 后无同步记录(堡垒机无主库操作权限);
-
4月9日10:30 开发通过调用链随机抽取数据发现当时注册成功但数据库无数据;
-
4月9日10:45 开发通过后台接口查验,发现数据库无数据(后台);
-
4月9日10:50 申请堡垒机主库访问权限;
-
4月9日11:00 确认主库4月8日18:30之前无数据;
-
4月9日11:10 让开发查询小于4月8日最后一条数据,发现数据时间为4月2日12:11;
-
4月9日11:15 安排开发开发登录/注册拦截功能,并批量将问题用户缓存删除;
-
4月9日11:20 让DBA操作用户关键表结构,将主键+100万的操作;
-
4月9日12:00 DBA无法通过脚本+100w修改数据库自增主键;
-
4月9日12:20 让DBA对关键表进行insert数据,并指定主键操作;
-
4月9日12:30 DBA将所有的数据同步任务停止,批量完成主键修改;
-
4月9日13:00 将区间用户4月2日至4月9日所有的新用户导出;
-
4月9日14:00 讨论影响范围以及具体方案;
-
4月9日14:30 某云来现场复盘该问题,并制定后续方案;
-
4月9日15:00 上线第一版拦截;
-
4月9日15:33 发现用户数据库链接数过多,无法链接;
-
4月9日15:40 查看监控发现数据库监控指标除了链接数,其他无问题;
-
4月9日15:45 DBA和现场运维尝试修改数据库链接数,修改几次失败;
-
4月9日15:50 已无数据进行;
-
4月9日15:52 发现项目初始化链接过多,安排开发将初始化链接降到10/20,最大降到50/100;
-
4月9日15:55 链接数据库发现大量的慢sql,基于主键的查询也几百秒了;
-
4月9日16:00 kill一批大于2秒的sql,发现还慢,执行explain发现explain都得执行十来秒,初步怀疑磁盘有问题;
-
4月9日16:05 再次无法连接;
-
4月9日16:10 让驻场运维开始kill 慢sql,同时询问有无办法进行漂移;
-
4月9日16:20 偶然听到旁边一运维哥们说了一句备份的事,并确认复盘完了怕现有实例有问题,进行一次全量备份;
-
4月9日16:25 停止掉全量备份,业务恢复;
-
4月9日17:00 监测到还有漏网用户进来;
-
4月9日18:00 开发修改代码上线,彻底堵住;
某云扩容机制
用户申请扩容流程
-
创建临时实例
-
将主实例最近的全量备份恢复到临时实例
-
然后追加binlog和主实例保持同步
-
修改VIP链接地址,将主vip指向临时实例,从实例的同步也从临时实例同步(这之间会有一些缓存处理机制,保证数据不丢失,只会闪断)
-
修改rds的元数据信息,将原主标记为临时,临时标记为主实例
-
释放元数据为临时实例的节点
问题分析
在扩容的时候,第4部成功,第5部卡住,导致流程中断。
-
4月8日14点左右 调试任务时,尝试将中断任务恢复,但恢复失败;
-
4月8日14:23 直接手动操作,跳过步骤5,直接执行步骤6
-
但是此时rds的元数据中新的实例还是临时实例的标签,但实际上已经变成了主实例,后端操作程序并没有做强校验,只是把临时实例上的同步给中断,进入待释放状态;
-
直到17:30分,才彻底释放完成,因此vip上连接的主实例丢失,也无法通过后端进行修复;
-
4月8日18:05,通过元数据发现的主实例,其实4月2日的主实例
-
4月8日18:25 运维通过手动挂载的实例,其实数据是不一致的;
-
4月9日12:00 让DBA更改自增主键时,大数据在做同步数据初始化操作,导致锁表,无法操作;
-
4月9日15:33 运维全量备份导致表被锁
问题处理
说明:
-
由于后续业务流程中用户主键作为一个业务唯一标识关联用户数据;
-
当4月8日18:25分恢复数据库后,在4月2日到4月9日12点调整主键id之间的用户数据都可能会错乱;
-
可能A用户4月2日来的时候id是3,4月8日18:30分后再来可能变成了5,B用户可能变成了3
处理:
-
针对之间的用户进行登录、注册拦截;
-
将这批用户的缓存全部清空;
-
将主键id进行手动扩容;
-
然后针对业务数据进行清洗处理;
-
由于涉及到业务,具体处理措施不在此处明说
-
最后放开这批用户,让用户进行操作
事后总结
-
生产无小事,运维的任何操作必须和业务同步;
-
经过业务允许后在可操作的时间范围内进行操作,禁止在业务高峰期操作;
-
针对所有的操作必须要有验收,具体验收规则根据实际情况来;
-
关联业务系统不能强依赖自增主键,业务主键必须自己生成,必须一个用户唯一,再来还是一样,比如业务主键hash后+业务主键后4位;
-
针对生产事故,必须重视,投入最大的资源去保障业务的稳定性;
想了解更多,请关注公众号5ycode
以上是关于记一次数据库“脑裂“问题的复盘的主要内容,如果未能解决你的问题,请参考以下文章