通过报错信息可知,worker 线程在回放事务 '471c2974-f9bb-11eb-afb1-52540010fb89:88313207' 时,由于要插入的记录主键冲突报错。
主机重启前,主从同步正常,主机重启后,主从同步由于主键冲突报错,对比了冲突主键所在行记
录在主从库是一致的,初步分析事务 '471c2974-f9bb-11eb-afb1-52540010fb89:88313207' 在主机故
障前已经在从库进行了回放,那为何事务会重复回放呢?
在开启gtid模式下,如果指定 master_auto_position=1,start slave 时,从库会把
Retrieved_Gtid_Set 和 Executed_Gtid_Set 的并集发送给主库,主库将收到的并集和自己的
gtid_executed 比较,把从库 gtid 集合里缺失的事务全都发送给从库。
主机重启后,事务重复回放,表明 Retrieved_Gtid_Set 和 Executed_Gtid_Set 的并集中有 GTID 事务
丢失,导致重复获取事务执行引发主键冲突错误。Retrieved_Gtid_Set 和 Executed_Gtid_Set 均为内存变
量,MySQL 重启后,Retrieved_Gtid_Set 初始化为空值,从而推断出 Executed_Gtid_Set 有 GTID 事务丢
失。
Executed_Gtid_Set 来源于 gtid_executed 变量,gtid_executed 变量持久化介质有
mysql.gtid_executed 表和 binlog ,其中 mysql.gtid_executed 表是 MySQL 5.7 后引入的,在 MySQL 5.6 中,从库要使用 GTID ,必须要先设置 log_bin=on,log_slave_updates=on ,因为从库执行过的 GTID 只保留在 binlog 中。
gtid_executed 变量值陈旧,推断出 binlog 未实时持久化,我们看一下参数 sync_binlog :
通过以上分析,此次故障来龙去脉就清楚了:
Worker 线程报 1062 主键冲突错误 -->gtid_executed 信息陈旧 -->binlog 未实时持久化
搭建一主一从测试环境,通过 sysbench 模拟主库并发插入,从库主机暴力关机后,故障复现:
既然错误原因是事务重复执行,那跳过错误就好了,有如下两种方式,根据需要选取其中一种方式执行:
如果最新 binglog 丢失的 GTID 较多,手工执行比较繁琐,需要不断试错。可写一个存储过程批量执行:
待主从同步正常后,再取消参数 slave_skip_errors 设置重启 MySQL 。
1、DTS数据同步报错
2、源端用户user1拥有所有database的权限,包括select权限
3、使用user1用户登录源端MySQL,当指定database为database1,select被拒绝
4、从MySQL的物理表文件看,表的.frm和.ibd文件是正常的
5、将报错的表table1备份为table2,删除table1,select information_schema.columns、information_schema.tables可执行且不报错
6、将table2重命名为table1,select information_schema.columns、information_schema.tables再次报一样的错误
7、将table1重命名为table2,select information_schema.columns、information_schema.tables可执行且不报错
8、原因判断
参考: https://bugs.mysql.com/bug.php?id=63527
其他用户也遇到了与MySQL对象相关的information_schema.columns、information_schema.tables的select报错,但是涉及的MySQL对象为view,而我们这里为table。
view可以指定definer等,而table1的创建语法中没有找到这样的字眼。但是推测以某一种方式与definer相关联。
9、辅证
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)