复制成功 复制可以但粘贴不了

作者:唐龙哲

爱可生交付服务团队上海DBA , 负责 MySQL 数据库故障处理及日常维护 。擅长故障诊断

本文来源:原创投稿

*爱可生开源社区出品 , 原创内容未经授权不得随意使用 , 转载请联系小编并注明来源 。
一、背景描述最近在客户环境遇到一个 sql_slave_skip_counter 使用不规范引起的主从故障问题 。
我们知道 mysql 的主从复制是逻辑复制 , 所以 slave 在应用 relay log 的过程中 , 经常会遇到错误 , 而参数 sql_slave_skip_counter 可以设置跳过多少个 event  , 让从库 sql 继续回放 。但是如果 sql_slave_skip_counter 使用不当 , 也会造成主从数据不一致 。
以下为抓取的部分错误日志截图:可以看到为了跳过报错的 SQL  , 现场有手动设置过 SQL_SLAVE_SKIP_COUNTER=100000  , 表示跳过10万的 events  , 而 binlog event 事件的多少 , 与事务表/非事务表、及 binlog 日志模式有关 。

复制成功 复制可以但粘贴不了

文章插图
复制成功 复制可以但粘贴不了

文章插图
复制成功 复制可以但粘贴不了

文章插图
复制成功 复制可以但粘贴不了

文章插图
复制成功 复制可以但粘贴不了

文章插图
(5)模拟主库追加数据
-- 主库追加数据begin;insert into replica_innodb values(6,'innodb_006');commit;select * from replica_innodb where id=6\G*************************** 1. row *************************** id: 6msg: innodb_006-- 从库观察到IO及SQL线程状态为yes , 复制正常且Skip_Counter值递减 。show slave status\G*************************** 1. row ***************************Slave_IO_Running: YesSlave_SQL_Running: YesLast_Errno: 0Last_Error:Skip_Counter: 9949Exec_Master_Log_Pos: 4849Relay_Log_Space: 5210-- 从库检查事务表数据 , 未发现id=6的记录 select * from replica_innodb\G*************************** 1. row *************************** id: 1msg: innodb_001说明:上述操作并未将主库提交的事务应用到从库 。
现象说明:
(1)通过上述操作 , sql_slave_skip_counter=N(N>0) 重启 slave 复制线程后 , 从库开始跳过 event  , 每跳过一个 event  , N就减去1 , 直到N变成0 。在此期间 , 所有冲突的 sql 语句及正常的 sql 语句产生的 event 都被记录到该变量中 , 当N变成0后从库才开始执行当前的语句 。
并且当 Skip_Counter 值等于1 , 在对事务表操作时 , 并不是只跳过一个 event  , 而是跳过一个完整事务 , 该事务如果存在多条 sql  , 那么当报错发生时 , 会将剩余的 sql 操作一并跳过 , 直到遇到 xid event 为止 。例如: 报错发生在第一个 sql 语句 , 如果第二条 sql 语句影响1000行数据 , 那么主从就有1000行数据不一致 。
(2)观察从库复制正常 , IO 及 SQL 线程状态为 yes 、Skip_Counter 值递减 , 且 binlog 无新的日志产生 , 错误日志无报错信息 。
2.3 sql_slave_skip_counter 清零为了防止 sql_slave_skip_counter 对复制的影响 , 需要在错误跳过之后及时的恢复 , 将参数置为零 。
方式一:重启复制
注意:MySQL5.7、8.0 重启复制后 , Skip_Counter 计数器清零 , MySQL 5.6 此方法无效 。
stop slave;start slave;show global variables like 'sql_slave_skip_counter'\G*************************** 1. row ***************************Variable_name: sql_slave_skip_counterValue: 0方式二:手工设置为零 , 立即生效
stop slave;set global sql_slave_skip_counter=0;start slave;show variables like 'sql_slave_skip_counter'\G*************************** 1. row ***************************Variable_name: sql_slave_skip_counterValue: 0方式三:重启从库
三、总结规范使用 sql_slave_skip_counter  , 如果操作不当 , 极有可能跳过其他 events  , 并造成主从数据不一致 。
如果数据库数据量较小 , 大约60G左右 , 建议重做复制 。数据量超过60G大小 , 可以在 sql_slave_skip_counter 跳过之前 , 看一下当前 binlog event group 执行了哪些操作 。对于1032、1062错误尽量修补数据 , 让复制进程在从库应用变更 。
【复制成功 复制可以但粘贴不了】建议 MySQL 复制开启 GTID(全局唯一事务ID) , 该方式可以根据当前事务的变化快速判断主从数据一致性 , 也强化故障恢复以及容错能力 。需要注意:此方式在5.6不支持在线开启 GTID  , 需要先停库再进行 GTID 相关参数配置 。

    推荐阅读