pt-slave-restart在gtid模式下无法跳过错误,因mysql 8.0.23+禁用sql_slave_skip_counter且并行复制(slave_parallel_workers>0)时无法准确定位worker,必须先设为0再执行;推荐用原生命令或pt-table-checksum+sync修复。

pt-slave-restart 不能直接跳过 GTID 模式下的错误,除非先关掉并行复制,否则会报错 “Cannot skip transactions properly because GTID is enabled and slave_parallel_workers > 0”。
为什么 pt-slave-restart 在 GTID 模式下常失败
工具底层依赖 sql_slave_skip_counter,而 MySQL 8.0.23+ 在 gtid_mode = ON 时已彻底禁用该变量。它尝试注入空事务时,若 slave_parallel_workers > 0,就会因无法定位具体 worker 而中断,并抛出明确错误:
ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON
- 即使你只传了
--error-numbers=1062,工具也会在内部检查@@GLOBAL.slave_parallel_workers,发现大于 0 就拒绝执行 - 它不区分“当前错误是否真由并行写入引发”,只要并行开启,就放弃跳过逻辑
- 错误日志里不会显示 GTID 值,只提示配置冲突,容易误判为权限或连接问题
跳过前必须做的三件事
盲目执行 pt-slave-restart 可能扩大主从偏差。操作前务必确认:
- 查
SHOW SLAVE STATUS\G中的Last_SQL_Error,确认错误确实是业务可接受的(比如测试残留用户、临时表删除)而非主库误发重复 INSERT) - 运行
SELECT * FROM information_schema.tables WHERE table_schema='db_name' AND table_name='tbl_name';,验证从库缺失的表/记录是否本就不该存在 - 停写:确保应用层已暂停向主库写入,避免跳过期间又产生新冲突
实际执行命令与参数要点
正确流程是先降级为单线程,再调用工具,最后恢复并行:
- 临时关闭并行:
SET GLOBAL slave_parallel_workers = 0; - 执行跳过:
pt-slave-restart --user=root --password='xxx' --socket=/var/lib/mysql/mysql.sock --error-numbers=1062,1032 --verbose - 恢复并行(跳过成功后):
SET GLOBAL slave_parallel_workers = 8;
注意:--error-numbers 支持逗号分隔多个码,但不要加空格;--verbose 会输出中继日志位置和 GTID,方便后续核对;--quiet 则完全静默,不推荐首次使用。
比跳过更稳妥的替代方案
如果错误高频出现(比如每天都有 1062),说明主从数据基线已漂移,靠跳过只是掩盖问题:
- 用
pt-table-checksum全量校验差异,再用pt-table-sync修复——这是唯一能闭环验证的方式 - 对仅缺失表结构的场景(如
Last_SQL_Error是Table 'x.y' doesn't exist),优先在从库手动建表,而不是跳过 - GTID 模式下想跳过单个事务,应改用原生命令:
STOP SLAVE; SET GTID_NEXT='xxx:nnn'; BEGIN; COMMIT; SET GTID_NEXT=AUTOMATIC; START SLAVE;,避免工具封装带来的黑盒风险
真正麻烦的从来不是怎么跳过,而是跳过之后没人去查那条 id=120383 的记录为什么在从库多出来——它可能早就是脏数据,只是现在才爆出来。











