|
凌晨三点,线修复我被手机震醒。线修复客户那边的线修复数据库挂了,报错日志刷了整整一屏——主从同步断了,线修复binlog 文件损坏,线修复位置卡在一个谁都说不清的线修复偏移量上。 远程连上去,线修复看着那台服务器,线修复CPU 占用率 0%,线修复磁盘 IO 也是线修复 0。它活着,线修复又好像死了。线修复我喝了口凉掉的线修复咖啡,开始翻 MySQL 的线修复官方文档。网上有人说可以跳过损坏的线修复 binlog 直接强制同步,也有人说要重建从库。但这是个生产环境,数据量三个 T,重建从库意味着至少六小时的业务中断。 我盯着那个损坏的 binlog 文件,突然想到一个办法——用 mysqlbinlog 的 --stop-position 参数,把损坏点之前的所有事件先解析出来,手动重放到从库上。听起来简单,但问题是那个损坏点到底在哪?日志文件 1.2G,我不能一个个字节去试探。 我写了个小脚本,用二分法定位损坏位置。先试着解析文件中间的部分,如果报错,就往前一半;如果成功,就往后一半。反复十几次,终于把损坏点锁定在一个事务的中间。那个事务涉及三张表的更新,我手动构造了补偿 SQL,把那个事务的中间状态补完。 然后才是真正麻烦的部分——从库的 relay log 里还存着那个损坏事务的残留信息。直接 START SLAVE 会继续报错。我清空了 relay log,手动指定了新的同步起点。这一步操作,风险极大,稍有不慎就会造成主从数据不一致。我反复核对了三遍主库的 binlog 位置和从库的数据状态,才敢敲下回车。 凌晨五点四十分,SHOW SLAVE STATUS 显示 Seconds_Behind_Master: 0。同步恢复了,数据没丢,业务无感知。客户第二天早上发来消息说“昨晚一切正常”。 我盯着屏幕,突然觉得“在线修复”这个词挺有意思。它不是把系统停下来修好再启动,而是在系统运行的状态下,把故障一点点剔除出去。就像给飞行中的飞机换引擎,你不能让乘客下机,只能戴着护目镜和防火手套,在气流颠簸中拧螺丝。 后来我把这次的操作步骤写成了文档,发在团队群里。有人回复说“这操作太野了”,也有人问我“如果二分法定位失败怎么办”。我没回答。说实话,如果那次定位失败,我可能就得走重建从库的路了。但那种“在线”的压力,会逼着你找到那些文档之外的解法。 现在回想起来,那次修复真正难的不是技术,而是决定在什么时刻相信自己的判断,在什么时刻准备放弃。凌晨四点半的时候,我一度想放弃,打算直接重建从库。但看着监控里业务流量还在缓慢爬升,我知道一旦停下来,损失的就是真金白银。 于是我又坐回电脑前,把那杯凉咖啡喝完,继续跟那个损坏的 binlog 较劲。直到天亮,我才确认,那晚所有的冒险都是值得的。 |