slave-skip-errors=1062仅对新错误生效且需重启,对当前卡点无效;启用后会静默跳过所有后续1062,掩盖人为误写、双写等脏数据,导致不一致持续扩散,必须手动定位清理并溯源修复。

直接禁用 slave-skip-errors 并不能修复已产生的脏数据,它只对后续新错误生效;当前从库不一致状态必须手动识别、定位、清理,否则跳过行为会持续掩盖问题,让差异越滚越大。
为什么 slave-skip-errors = 1062 会让脏数据静默扩散
这个参数是静态配置项,写入 my.cnf 后必须重启 MySQL 才生效,且只影响“之后遇到的错误”,对已经卡住的复制线程完全无效。更危险的是:一旦启用,所有后续 1062 错误都会被自动跳过,包括那些本该报警的人为误写、应用双写、从库被绕过 read_only = ON 插入的脏行——你可能第二天才发现几十张表主键范围错乱、计数对不上、下游报表崩了。
常见误判点:
- 看到
SHOW SLAVE STATUS\G中Executed_Gtid_Set非空,就以为 GTID 已开,其实可能是旧从库残留值;真正权威依据只有SHOW VARIABLES LIKE 'gtid_mode'返回ON - 在主库误配
slave-skip-errors,不仅无效,还会干扰故障排查,掩盖真实复制异常 - 把
slave-skip-errors和sql_slave_skip_counter混用,前者是全局策略,后者是单次动作,场景和风险完全不同
确认脏数据是否真实存在(不是误报)
别急着删或跳,先验证冲突是否真导致不一致。执行以下三步:
- 从
SHOW SLAVE STATUS\G的Last_SQL_Error字段提取冲突主键值,例如Duplicate entry '12345' for key 'PRIMARY' - 在从库执行
SELECT * FROM 表名 WHERE 主键 = 12345;,记录该行完整内容 - 到主库查同一条记录:
SELECT * FROM 表名 WHERE 主键 = 12345;,比对字段值、时间戳、是否已被逻辑删除
如果从库多出一行、或字段值明显陈旧(比如主库已更新为 status = 'done',从库仍是 'pending'),那就是真实脏数据;如果两边完全一致,说明只是重复插入,可安全跳过或删掉从库那行。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
清理脏数据的优先级顺序
修复顺序按风险从低到高排列,能不动复制状态就不动:
- 若确认脏行是人为误插(比如 DBA 在从库执行过
INSERT),且业务允许,优先在从库执行:SET sql_log_bin = 0; DELETE FROM 表名 WHERE 主键 = 12345;—— 这比注入空事务更安全、可审计、不扰动 GTID 集合 - 若主库那条 INSERT 来自某次上线脚本或迁移任务,且从库缺失该行,应补插而非跳过;用
mysqlbinlog --base64-output=DECODE-ROWS -v解析对应 binlog 定位原始语句,手工重放 - 严禁直接改
slave-skip-errors后重启来“解决”当前卡点——它对当前事务无效,还可能让下个 1062 自动跳过,错过修复窗口
跳过之后必须立刻做的三件事(缺一不可)
跳过只是让 SQL 线程跑起来,不是问题终结:
- 查源头:用
mysqlbinlog --base64-output=DECODE-ROWS -v解析报错位置附近的 relay log,确认那条 INSERT 是谁发的、带什么 trace_id、有没有幂等控制 - 清残留:检查
SELECT @@read_only;是否为ON,翻general_log或审计日志,找所有在从库执行过 DML 的客户端 IP 和账号 - 校一致性:至少抽样核验关键表的
MIN(id), MAX(id), COUNT(*),有条件务必跑pt-table-checksum全量比对;特别注意auto_increment_offset和auto_increment_increment主从是否匹配
最常被忽略的一点:GTID_NEXT 值抄错一位、COMMIT 前连接断开、或没执行 STOP REPLICA SQL_THREAD 就设 GTID_NEXT,都会让从库进入不可恢复的 GTID 不一致状态——这不是配置问题,是状态机级损坏,只能重建从库。










