sql_slave_skip_counter 经常不生效,因为它仅在 gtid_mode=OFF、binlog_format=STATEMENT、非事务引擎且 relay_log_recovery=OFF 的旧环境中有效;GTID 模式下报错 ERROR 1858,ROW 格式报 ERROR 1374,MySQL 8.0.26 起已被 sql_replica_skip_counter 取代。

不能直接用 sql_slave_skip_counter 跳过“当前报错那条 SQL”——它跳的是“下一条事件”,且只在特定条件下生效,多数生产环境已失效。
为什么 sql_slave_skip_counter 经常不生效
这个变量在 MySQL 8.0.23+ 已被标记为 deprecated,8.0.26 起正式由 sql_replica_skip_counter 替代。更关键的是,它根本不是“跳错误语句”,而是跳 relay log 里的下一个 event:
- 它仅对
binlog_format = STATEMENT有效;ROW格式下执行会报ERROR 1374 - GTID 模式(
gtid_mode = ON)下直接报错:ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON - 必须先停 SQL 线程:
STOP SLAVE SQL_THREAD;(不是STOP SLAVE;) - 若启用了多线程复制(
slave_parallel_workers > 0),行为不可靠,建议临时设为 0
真正能用 sql_slave_skip_counter 的场景
仅限于明确满足以下全部条件的旧环境:
-
gtid_mode = OFF(确认方式:SHOW VARIABLES LIKE 'gtid_mode';) binlog_format = STATEMENT-
relay_log_recovery = OFF(否则跳过无效) - 出错语句是非事务引擎(如 MyISAM)的单条 DML;InnoDB 事务内出错时,它无法精准跳到错误语句内部
操作顺序必须是:STOP SLAVE SQL_THREAD; → SET GLOBAL sql_slave_skip_counter = 1; → START SLAVE SQL_THREAD;
跳过之后必须立刻验证的三件事
跳过只是让 SQL 线程跑起来,不代表数据一致:
- 主从执行
SELECT COUNT(*) FROM db.table;,行数必须完全一致(尤其注意带 WHERE 的 DELETE/UPDATE 是否漏同步) - 观察
SHOW SLAVE STATUS\G中Exec_Master_Log_Pos是否推进、Seconds_Behind_Master是否持续下降,且与主库SHOW MASTER STATUS的Position差距不再扩大 - 主库执行测试插入:
INSERT INTO test_sync VALUES (UNIX_TIMESTAMP(), 'verify');,立刻去从库查这条记录是否存在
真正麻烦的从来不是跳过那条报错语句,而是跳过之后发现 auto-increment 偏移错位、唯一索引残留脏数据、或 binlog_format 不一致导致后续事务无法解析——这些都不会报错,但会让不一致静默扩散。


















