| 背景
在MySQL5.7版本中,开启并行复制后,设置relay-log-recovery=1,从库启动后偶尔会报错,类似于https://bugs.mysql.com/bug.php?id=83713。所以尝试将relay-log-recovery设置为0,观察会发生什么。
| 环境
- MySQL5.7.22
- GTID模式
- relay-log-recovery=0
- relay_log_purge=off
- sync_relay_log = 10000
- relay_log_info_repository = TABLE
- 不开启并行复制
| 模拟relay-log没有sync完全
Retrieved_Gtid_Set < Executed_Gtid_Set
停掉slave,查看相关信息
[
关闭数据库stopmysql
$
查看最后一个relaylog中的最后一个事务的GTID为2662c965-fdb2-11e8-8157-0cc47a3aae0d:11822
$
用以下命令模拟relaylog丢失,这样mysql重新启动的时候初始化的Retrieved_Gtid_Set集合会比Executed_Gtid_Set集合小
$
启动数据库startmysql
$
查看复制状态是否正常,复制正常。
且看到是从2662c965-fdb2-11e8-8157-0cc47a3aae0d:11823开始拉取binlog,因为UNION的GTID集合为2662c965-fdb2-11e8-8157-0cc47a3aae0d:1-11822。
[
查看error.log相关信息
2018
查看下个relaylog信息
$
查看再下个relaylog信息,发现是从2662c965-fdb2-11e8-8157-0cc47a3aae0d:11823开始拉取日志
$
再次查看mysql-relay-bin.000017中的内容,最后记录如下,多了WARNING的信息
$
Retrieved_Gtid_Set > Executed_Gtid_Set
停掉slave的sql线程,模拟Retrieved_Gtid_Set > Executed_Gtid_Set,如下:
[
关闭数据库stopmysql
$
查看mysql-relay-bin.000011最后一个事务GTID为2662c965-fdb2-11e8-8157-0cc47a3aae0d:7604
$
执行以下命令将GTID为2662c965-fdb2-11e8-8157-0cc47a3aae0d:7600的事务截掉一半,2662c965-fdb2-11e8-8157-0cc47a3aae0d:7601、2662c965-fdb2-11e8-8157-0cc47a3aae0d:7602、2662c965-fdb2-11e8-8157-0cc47a3aae0d:7603、2662c965-fdb2-11e8-8157-0cc47a3aae0d:7604全部抹掉
$
启动数据库startmysql
$
查看复制状态是否正常,显示正常。
[
查看error.log
2018
查看下一个relaylog的信息
$
查看再下一个relaylog的信息,发现确实会重新去拉取2662c965-fdb2-11e8-8157-0cc47a3aae0d:7600这个GTID对应的日志
$
| 总结
从error.log中能看到,MySQL重启后,Slave SQL thread会根据mysql.slave_relay_log_info表中记录的位置点信息去starting replication
[
观察两种情况下error.log日志中内容,发现:
- Retrieved_Gtid_Set < Executed_Gtid_Set下,SQL线程按mysql.slave_relay_log_info表中记录的位置点信息(mysql-relay-bin.000017,186094)去starting replication时,发现对应的日志信息不存在(mysql-relay-bin.000017日志被我截断到185090),就继续执行下一个relaylog。因为Executed_Gtid_Set > Retrieved_Gtid_Set,UNION集合就是Executed_Gtid_Set,所以新生成的relaylog里拉取的第一个GTID是Executed_Gtid_Set的下一个GTID,SQL线程正常回放。
- Retrieved_Gtid_Set > Executed_Gtid_Set下,error.log中有如下信息。因为在Executed_Gtid_Set小于Retrieved_Gtid_Set情况下,被截断的GTID还未被执行,所以SQL线程会尝试去执行,执行了发现事务不完整,会进行rollback;且MySQL启动后,这个不完整的事务会被放到last_received_GTID中,这样MySQL会根据UNION(@@global.gtid_executed, Retrieved_gtid_set - last_received_GTID)集合,IO线程会重新拉取这个不完整的事务,此时拉取后事务完整,SQL线程正常回放。
2018
| 问题
在GTID模式下,设置relay-log-recovery=0会不会影响从库的数据一致性?
并行复制下呢?
| 作者简介
韩杰 沃趣科技MySQL数据库工程师
熟悉mysql体系架构、主从复制,熟悉问题定位与解决。