1.GTID不一致的原因与影响
1.在从库上执行过变更命令
-
master上没有执行,但在slave上执行过
例如在slave上某张表执行了ddl
,在master上执行对应表相关的操作时,可能会报错,但ddl
仍然会计入binlog(ddl作为事务 无论提交还是回滚都会计入binlog,以保持主从一致)而在slave上会执行成功,导致主从gtid不一致 -
master和slave都执行过相同的命令,都写入了binlog 导致gtid不一致 例如
flush error logs
FLUSH LOGS, FLUSH BINARY LOGS, FLUSH TABLES WITH READ LOCK (with or without a table list), and FLUSH TABLES tbl_name ... FOR EXPORT are not written to the binary log in any case
2.主库crash
假设主库在write binlog之后,sync 之前,同时备库也拉取了这些未sync的binlog。此时主库宕机,主库一部分 binlog 未落盘,但这部分binlog已经传到了备库,那么备库会比主库多一些事务。因此主库重启后,重新构造 gtid_executed_set 时会比备库少一些gtid。
3.replace into
replace
操作是在自增主键的情况下,遇到唯一键冲突时执行的是 delete+insert
,但是在记录 binlog
时,却记录成了update
操作,update
操作不会涉及到 auto_increment
的修改。备库应用了 binlog
之后,备库的表的 auto_increment
属性不变。
如果主备库发生主从切换,备库变为原来的主库,在新主库上进行replace into 操作,可能会导致主键id冲突
4.网络中断
主库执行一个大事务时,主从网络中断,主库提交事物,但从库没有接受到,导致主从gtid不一致
5.主库手动rm 正在使用的binlog
在复制状态正常下,把主库正在用的 binlog 日志 rm 手动删除
进入主库执行 flush logs 刷新日志,这时 binlog 会重新生成刚刚删除的 binlog 文件,此时观察主库的 binlog 日志是连续的,index 索引文件里面出现了两个刚刚 rm 手动删除的 binlog 日志信息,即 index 文件记录着有两个相同文件
当正在用的 binlog 文件被手动rm掉时,binlog 文件计数器是不会受到影响,当在 binlog 文件刷新后(重启、flush log 、binlog 文件写满等),binlog 文件计数器会根据当前最大 binlog 文件+1
但主库实际已经丢失一个 binlog.000006 ,现有的 binlog.000006 和上一个 binlog.000005 的 gtid 也不连续,只是文件名仍连续
2.GTID不一致如何修复
-
不一致情况严重时,且binlog未purge,考虑重新建立主从同步
-
手动在线修复从库gtid比主库多的情况:在主库上执行
SHOW MASTER STATUS\G
命令,获取主库的GTID_EXECUTED
和BINLOG
文件名和位置信息;
在从库上执行STOP SLAVE;
命令,停止复制;
在从库上执行SET @@GLOBAL.GTID_PURGED='gtid_executed_on_master'
命令,将从库上的GTID信息手动设置为主库上的GTID
信息;
在从库上执行START SLAVE;
命令,重新启动复制。
3.如何提前发现GTID不一致
- 假设要在salve上变更操作 设置
set sql_log_bin = 0
- 每当发生主从报错或者主从切换后,都进行一次主从数据校验
- 分析binlog,找到对应GTID的具体SQL来判断需要跳过还是修复数据