
万答#4,延迟从库加上MASTER_DELAY,主库宕机后如何快速恢复服务
当主库宕机后,延迟从库如何才能"取消"主动延迟,以便恢复服务?
问题描述
本问题来自一位群友,他遇到的情况我简单归纳一下:
● 实例A是主库,B是延迟从库(设置了延迟7200秒)。
● 当A挂掉后(已无法连接,或无法启动),希望用B提升成主库。
● 但是在B上执行 change master to MASTER_DELAY=0 后,B上已经保存的7200秒的relay文件也会被清除掉,并尝试再次从A获取binlog,这样会造成7200秒的数据丢失,未能达成目的。
TA想问:在这样的场景下,还有办法让B库尽快跑完这7200秒延迟数据吗,或者正确的办法是什么呢?
问题解决
先回答问题:这个需求是有办法达成的(而且还不只一种方法),最正确的方法也并不麻烦/复杂(看到最后),只不过有些小窍门要注意下。
方法1,修改系统时间
也就是修改B主机的系统时间,将其往后调整超过7200秒,然后重启slave线程,就能让SQL_THREAD继续应用relay log了。所有relay log应用完毕后,再将系统时间修改回来。
这种方法(潜在)影响很大,可能对其他系统应用有影响,或者MySQL里部分涉及到日期时间的结果也会受到影响,非常不推荐。
方法2,自行手动恢复relay log/binlog
当主库(A)宕机后,查看当前slave的状态:
可以看到这时候有387秒的落后,主动延迟7200秒,还有6814秒之后才能应用最新的relay log。虽然事务有延迟,但其实slave已经把binlog都复制过来了,在relay log里。
现在,只需要手动把这中间的差异数据拿出来apply就可以了。解析relay log,找到对应master binlog pos = 746的位置,或者直接指定realy log pos = 361的位置也可以:
确认对应的事务是存在的,接下来就可以利用relay log恢复数据了。
当然了,如果此时A主机还可以连接,只是mysqld服务无法启动的话,亦可直接用A主机上的binlog进行恢复。
这种方法需要细心谨慎,手眼配合密切,容易出错,因此也不推荐。
方法3,正确理解MASTER_DELAY,一键搞定
前面铺垫了那么多,看起来想要让延迟从库快速恢复好像有点麻烦的样子。
事实上,只要正确理解,一键命令就搞定了。
当主库发生故障宕机后,binlog其实已经都复制到从库并写入成relay log了。当然了,为避免误操作,建议先备份relay log。
接下来的操作很重要,看准了,一定不要做错:
主库虽然宕机了,但从库上只有IO_THREAD会报告连接错误,SQL_THREAD还是可以正常工作的。
上述操作的关键点在于,修改 MASTER_DELAY 时并没有先停掉 IO_THREAD,否则会清空所有的relay log,尝试去主库再次拉取。
再次启动 SQL_THREAD 之后,从库就会继续应用relay log,待到全部应用完毕后,完成必要的数据校验,即可提成成为新的主库,对外提供服务了。
看,真的挺简单的吧。
现在来验证下:完全停掉SLAVE服务后修改MASTER_DELAY值,再启动SLAVE服务,此时会清空重置relay log。
所以,请记住了,当延迟从库要修改延迟设置时,只需重启SQL_THREAD,千万别图省事重启整个SLAVE服务,这样relay log就不会被清空重置了,也就能实现快速恢复并提升为主库。为以防万一,也请务必备份好relay log。
因为relay log是由 IO_THREAD 负责的,所以只要 IO_THREAD 不重启,就不会清空重置。看下MySQL文档中关于relay log的说明:
P.S,本文使用的GreatSQL 8.0.22-13,关于这个版本的说明详见 GreatSQL,打造更好的MGR生态。
本文转载自公众号GreatSQL
