共计 5314 个字符,预计需要花费 14 分钟才能阅读完成。
欢送来到 GreatSQL 社区分享的 MySQL 技术文章,如有疑难或想学习的内容,能够在下方评论区留言,看到后会进行解答
当主库宕机后,提早从库如何能力 ” 勾销 ” 被动提早,以便复原服务?
问题形容
本问题来自一位群友,他遇到的状况我简略演绎一下:
- 实例 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 利用结束后,再将零碎工夫批改回来。
# 批改零碎工夫,减少 7200 秒
[root@greatsql]# date -s "`date --date'7200 second'`"
# 重启 slave 线程
[root@GreatSQL](none)> STOP SLAVE; START SLAVE;
留神:这种办法(潜在)影响很大,可能对其余零碎利用有影响,或者 MySQL 里局部波及到日期工夫的后果也会受到影响,十分不举荐。
办法 2,自行手动复原 relay log/binlog
当主库(A)宕机后,查看以后 slave 的状态:
[root@GreatSQL](none)> SHOW SLAVE STATUS\G
...
Master_Log_File: binlog.000011
Read_Master_Log_Pos: 2671
Relay_Log_File: relay-bin.000005
Relay_Log_Pos: 361
Relay_Master_Log_File: binlog.000011
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
...
Exec_Master_Log_Pos: 746
Relay_Log_Space: 2704
...
Seconds_Behind_Master: 387
...
SQL_Delay: 7200
SQL_Remaining_Delay: 6814
Slave_SQL_Running_State: Waiting until MASTER_DELAY seconds after master executed event
能够看到这时候有 387 秒的落后,被动提早 7200 秒,还有 6814 秒之后能力利用最新的 relay log。尽管事务有提早,但其实 slave 曾经把 binlog 都复制过去了,在 relay log 里。
Read_Master_Log_Pos: 2671 <-- 已读取到最新的 binlog 了,pos = 2671
Relay_Log_File: relay-bin.000005 <-- 对应的 relay log
Relay_Log_Pos: 361 <-- 对应的 relay log pos
...
Exec_Master_Log_Pos: 746 <-- 但只 apply 到 pos = 746
当初,只须要手动把这两头的差别数据拿进去 apply 就能够了。解析 relay log,找到对应 master binlog pos = 746 的地位,或者间接指定 realy log pos = 361 的地位也能够:
[root@greatsql]# ls -la relay-bin.*
-rw-r----- 1 mysql mysql 418 Jun 13 13:31 relay-bin.000004
-rw-r----- 1 mysql mysql 2286 Jun 13 13:33 relay-bin.000005
-rw-r----- 1 mysql mysql 58 Jun 13 13:31 relay-bin.index
[root@greatsql]# mysqlbinlog --base64-output=decode-rows -vvv relay-bin.000005
...
# at 196
#700101 8:00:00 server id 5001 end_log_pos 0 CRC32 0xaf7e0f79 Rotate to binlog.000011 pos: 746
# at 240
#210613 11:26:08 server id 5001 end_log_pos 0 CRC32 0xfa7fd769 Start: binlog v 4, server v 8.0.22-13 created 210613
11:26:08
# at 361
#210613 13:33:41 server id 5001 end_log_pos 825 CRC32 0xd5161853 GTID last_committed=1 sequence_number=3
rbr_only=yes original_committed_timestamp=1623562421106412 immediate_commit_timestamp=1623562421106412 transaction_length=275
...
确认对应的事务是存在的,接下来就能够利用 relay log 复原数据了。
[root@greatsql]# mysqlbinlog relay-bin.000005 --start-position=361 | mysql -S./mysql.sock -f
当然了,如果此时 A 主机还能够连贯,只是 mysqld 服务无奈启动的话,亦可间接用 A 主机上的 binlog 进行复原。
这种办法须要仔细审慎,手眼配合亲密,容易出错,因而也不举荐。
办法 3,正确理解 MASTER_DELAY,一键搞定
后面铺垫了那么多,看起来想要让提早从库疾速复原如同有点麻烦的样子。
事实上,只有正确理解,一键命令就搞定了。
当主库产生故障宕机后,binlog 其实曾经都复制到从库并写入成 relay log 了。当然了,为防止误操作,倡议先备份 relay log。
接下来的操作很重要,看准了,肯定不要做错:
# 只敞开 SQL_THREAD,而不是间接敞开整个 SLAVE 服务
[root@GreatSQL](none)> STOP SLAVE SQL_THREAD;
# 批改 MASTER_DELAY,使之不再提早
[root@GreatSQL](none)> CHANGE MASTER TO MASTER_DELAY=0;
# 再次启动 SQL_THREAD
[root@GreatSQL](none)> START SLAVE SQL_THREAD;
主库尽管宕机了,但从库上只有 IO_THREAD 会报告连贯谬误,SQL_THREAD 还是能够失常工作的。
上述操作的关键点在于,批改 MASTER_DELAY 时并没有先停掉 IO_THREAD,否则会清空所有的 relay log,尝试去主库再次拉取。
再次启动 SQL_THREAD 之后,从库就会持续利用 relay log,待到全副利用结束后,实现必要的数据校验,即可提成成为新的主库,对外提供服务了。
看,真的挺简略的吧。
当初来验证下:齐全停掉 SLAVE 服务后批改 MASTER_DELAY 值,再启动 SLAVE 服务,此时会清空重置 relay log。
# 主库宕机后,查看 SLAVE 状态
[root@GreatSQL](none)> SHOW SLAVE STATUS\G
...
Master_Log_File: binlog.000017
Read_Master_Log_Pos: 471
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: binlog.000017
Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
...
Exec_Master_Log_Pos: 196
...
Seconds_Behind_Master: 69
...
SQL_Delay: 7200
SQL_Remaining_Delay: 7132
Slave_SQL_Running_State: Waiting until MASTER_DELAY seconds after master executed event
...
# 查看 relay log 状态
[root@greatsql]# ls -la relay-bin.*
-rw-r----- 1 mysql mysql 213 Jun 13 15:11 relay-bin.000001
-rw-r----- 1 mysql mysql 596 Jun 13 15:11 relay-bin.000002
-rw-r----- 1 mysql mysql 58 Jun 13 15:11 relay-bin.index
# 敞开 SLAVE 服务,批改 MASTER_DELAY,再启动 SLAVE 服务
[root@GreatSQL](none)> STOP SLAVE; CHANGE MASTER TO MASTER_DELAY=0; START SLAVE;
# 再次查看 relay log,发现被清空重置了
[root@greatsql]# ls -la relay-bin.*
-rw-r----- 1 mysql mysql 156 Jun 13 15:18 relay-bin.000001
-rw-r----- 1 mysql mysql 29 Jun 13 15:18 relay-bin.index
所以,请记住了,当提早从库要批改提早设置时,只需重启 SQL_THREAD,千万别图省事重启整个 SLAVE 服务,这样 relay log 就不会被清空重置了,也就能实现疾速复原并晋升为主库。为以防万一,也请务必备份好 relay log。
因为 relay log 是由 IO_THREAD 负责的,所以只有 IO_THREAD 不重启,就不会清空重置。看下 MySQL 文档中对于 relay log 的阐明:
# 原文出处 https://dev.mysql.com/doc/refman/8.0/en/replica-logs.html
The replica's relay log, which is written by the replication I/O thread, contains the transactions read from the replication source server's binary log. The transactions in the relay log are applied on the replica by the replication SQL thread. For information about the relay log, see Section 17.2.4.1,“The Relay Log”.
P.S,本文应用的 GreatSQL 8.0.22-13,对于这个版本的阐明详见 GreatSQL,打造更好的 MGR 生态。
延长浏览
- 13.4.2.1 CHANGE MASTER TO Statement, https://dev.mysql.com/doc/ref…
- 18.17.2.4 Relay Log and Replication Metadata Repositories, https://dev.mysql.com/doc/ref…
- 18.17.4.11 Delayed Replication, https://dev.mysql.com/doc/ref…
Enjoy GreatSQL :)
文章举荐:
技术分享 | MGR 最佳实际 (MGR Best Practice)
https://mp.weixin.qq.com/s/66…
技术分享 | 万里数据库 MGR Bug 修复之路
https://mp.weixin.qq.com/s/Ia…
Macos 零碎编译 percona 及局部函数在 Macos 零碎上运算差别
https://mp.weixin.qq.com/s/jA…
技术分享 | 利用 systemd 治理 MySQL 单机多实例
https://mp.weixin.qq.com/s/iJ…
产品 | GreatSQL,打造更好的 MGR 生态
https://mp.weixin.qq.com/s/By…
产品 | GreatSQL MGR 优化参考
https://mp.weixin.qq.com/s/5m…
对于 GreatSQL
GreatSQL 是由万里数据库保护的 MySQL 分支,专一于晋升 MGR 可靠性及性能,反对 InnoDB 并行查问个性,是实用于金融级利用的 MySQL 分支版本。
Gitee:
https://gitee.com/GreatSQL/Gr…
GitHub:
https://github.com/GreatSQL/G…
微信 &QQ 群:
可扫码增加 GreatSQL 社区助手微信好友,发送验证信息“加群”退出 GreatSQL/MGR 交换微信群,亦可间接扫码退出 GreatSQL/MGR 交换 QQ 群。
本文由博客一文多发平台 OpenWrite 公布!