今日关键词:主从同步失败、1032/1062、并行复制MTS、GTID、生产排障
MySQL主从同步中断是DBA日常最头疼的问题之一。Sla ve_SQL_Running突然变成No,报错1032或1062,相信不少同学都遇到过。前几篇文章介绍了主从复制的搭建、监控和延迟排查,有读者反馈说配置都做好了,但偶尔从库查不到新数据,打开监控一看报错,整个人都懵了,完全不知道从何查起。
说实话,第一次遇到这种场景确实容易手忙脚乱。线上从库查不到新数据,监控里显示Sla ve_SQL_Running: No,错误码1032,折腾一下午才修好。后来翻官方文档、踩了几次坑,慢慢总结出一套排查套路。这里整理的是MySQL主从同步失败五大类高频诱因,涵盖报错定位、底层原理和解决方案。面试被问“主从同步为什么中断”,或者线上突然挂了需要快速定位,翻这篇就够了。
一、数据层:最高频,面试必考
1. 表没有主键/唯一索引(报错1032)
这是最常见的坑之一。假设库存日志表tb_inventory_log忘了加主键,表就这么裸着跑了两个月。开启并行复制sla ve_parallel_workers=8之后,双从库同时报错:
Worker 1 failed executing transaction ... Error_code: 1032; Can't find record in 'tb_inventory_log'; handler error HA_ERR_KEY_NOT_FOUND
为什么会出现这种情况?MySQL 8.0默认RBR(基于行的复制),主库执行UPDATE/DELETE时,Binlog要记录“改了哪一行”。有主键的时候靠主键精确定位;没主键的时候,InnoDB自己生成一个隐式row_id当聚簇索引。但这个row_id是表级自增计数器——主从库各算各的,完全不互通。并行复制一开,事务执行顺序错乱,从库的row_id跟主库对不上,直接报1032。
应急处理:STOP SLA VE SQL_THREAD; SET GLOBAL sql_sla ve_skip_counter = 1; START SLA VE SQL_THREAD; 跳过事务能临时恢复,但治标不治本。根本解决方案只有一条:给所有表加显式主键。MySQL 8.0.30及以上可以使用不可见主键ALTER TABLE ... ADD id INT AUTO_INCREMENT PRIMARY KEY INVISIBLE,不用改业务代码。
面试话术:无主键表在RBR+并行复制下,依赖隐式row_id定位行,但row_id是表级自增计数器、主从不互通,事务乱序回放导致定位失败报1032,这是MySQL并行复制的典型坑点。
2. 主键/唯一键冲突(报错1062)
Duplicate entry 'xxx' for key 'PRIMARY', Error_code: 1062
这个报错意味着从库已经有了这条数据,主库又插入了一份相同主键的。常见场景:
- 从库被人手动写入了数据。
- 运维临时改了个订单状态,主库后来也改了同一条,冲突了。
- 多主架构路由没做好:两个主库同时写入同一条用户数据,互相同步就撞车。
- 同步中断恢复时没做数据对齐:手动导入了一部分数据,恢复同步后跟主库新数据冲突。
修复方法:找到冲突行,删掉从库多余数据(对齐主库),再启动同步。紧急情况可跳过事务,但之后必须做数据一致性校验。
3. 从库数据缺失/多余
表现为1032(主库更新了从库没有的数据),或者同步正常但两边数据差距越来越大。典型场景:
- 搭建主从的时候没做全量备份,直接就开同步——存量数据天然不一致。
sql_sla ve_skip_counter用得太过频繁,跳着跳着一堆数据没同步。- 从库上跑了定时任务或报表,自己生成了主库没有的数据。
修复方法:用pt-table-checksum检查数据差异,pt-table-sync同步差异数据。严重的直接重做全量备份再恢复从库。
二、配置层:容易被忽视的隐藏冲击波
1. 复制账号权限不够
Access denied for user 'repl'@'xxx' (using password: YES)
初学者容易犯的一个错误:建立复制账号repl,只给了REPLICATION SLA VE权限。结果主库执行ALTER TABLE改表结构,从库回放时因为缺ALTER权限直接挂了。
解决:给复制账号开完整权限:
GRANT REPLICATION SLA VE, REPLICATION CLIENT ON *.* TO 'repl'@'%'; GRANT SELECT, INSERT, UPDATE, DELETE, ALTER, CREATE, DROP ON *.* TO 'repl'@'%';
2. 主从 sql_mode 不一样
Error Code: 1055. Expression #1 of ORDER BY clause is not in GROUP BY clause
主库sql_mode没开ONLY_FULL_GROUP_BY,随便写GROUP BY语句都能跑;从库开启了严格模式,同样的SQL回放时语法校验不过,直接报错。
血的教训:主从 sql_mode 必须一模一样。新建从库时,先用SHOW VARIABLES LIKE 'sql_mode'把主库的值复制过来。
3. 字符集不一致
Incorrect string value: 'ð' for column 'nickname'
用户昵称里带了个emoji,主库是utf8mb4正常存,从库是utf8存不了,SQL线程直接中断。解决:主从统一utf8mb4 + utf8mb4_unicode_ci,my.cnf里配好:character_set_server = utf8mb4; collation_server = utf8mb4_unicode_ci。
三、Binlog 与复制参数:配错一个,全挂
1. binlog_format 不一致
主库STATEMENT,从库ROW,从库解析不了就挂了。MySQL 8.0默认ROW,主从统一设为binlog_format=ROW,一劳永逸。
2. GTID 模式翻车
GTID是MySQL 8.0的核心特性,但坑也不少:GTID conflict: Found a GTID that is already in the gtid_executed set
一个典型场景:同步中断后慌了,手动执行了reset sla ve,清空了从库的gtid_executed。恢复同步时GTID全乱了,只能重搭。教训:不要随便reset sla ve!GTID冲突的正确做法是reset sla ve all然后重新从主库拉GTID。
3. RelayLog/Binlog 文件损坏
Corrupted relay log file 'xxx-relay-bin.000001'
磁盘满、突然断电、误删日志都可能导致这个问题。预防措施就两条:binlog_checksum=CRC32开启校验,定期监控磁盘空间。
四、MySQL 8.0 并行复制(MTS)专属坑
开启了sla ve_parallel_workers之后性能确实上去了,但新坑也来了。面试特别喜欢问这个,用来区分对8.0的熟悉程度。
1. 多线程事务冲突
多个Worker线程并行回放,恰好操作了同一张表的同一行,直接死锁。解决办法:sla ve_preserve_commit_order=ON,保证从库事务提交顺序和主库一致。sla ve_parallel_workers别设太大,一般设为CPU核数的1/2到2/3就行。
2. WRITESET 依赖检测失效
MySQL 8.0的并行复制有两种策略:LOGICAL_CLOCK(按提交时间)和WRITESET(按行哈希值判断冲突)。WRITESET模式性能更好,但它计算哈希值依赖主键/唯一键。没主键的表在WRITESET模式下哈希值算不出来,冲突检测直接失效——又绕回了第一个坑:所有表必须有主键。
五、DDL、大事务与特殊 SQL
1. 大表 DDL
主库对千万级订单表执行ALTER TABLE,跑了30分钟;从库回放时被业务查询的MDL锁卡住,超时报错。经验:DDL别在高峰期跑,大表能用Online DDL就用Online DDL,实在不行先分表再改。
2. 超大事务
批量删除100万行历史数据,生成了20GB的Binlog。从库IO拉取都拉了半天,SQL回放直接内存溢出。经验:大事务拆小,比如每次删10万行,分10次跑。从库的innodb_buffer_pool_size给够。
3. 特殊 SQL 不兼容
临时表CREATE TEMPORARY TABLE在STATEMENT模式下从库没法回放;自定义函数UDF主库有、从库没有也会报错。解决方案:统一用ROW模式复制。
六、人为操作:生产中最高频的翻车现场
其实很多同步故障不是MySQL的锅,是人干的。以下是四大禁区:
| 操作 | 后果 | 怎么防 |
|---|---|---|
| 从库手动增删改 | 主从数据不一致,报1032/1062 | 从库设super_read_only=ON |
频繁sql_sla ve_skip_counter | 数据差异越积越多 | 应急才能用,用完必须对齐数据 |
误执行reset master/sla ve | 同步链路直接断裂 | 禁止!操作前先备份 |
| 主库Binlog过期清理太快 | 从库消费不完日志就没了 | expire_logs_days设7~15天 |
面试怎么答?
如果面试官问:“请说说MySQL主从同步失败的常见原因?”回答时可以按照数据层、配置层、Binlog参数、并行复制、DDL/大事务、人为操作这几个维度展开,每个维度给出典型报错和根本原因。
生产避坑清单
- ✅ 所有表必须有显式主键,MySQL 8.0.30及以上可用不可见主键
- ✅ 主从版本、sql_mode、字符集、binlog_format、GTID开关完全统一
- ✅ 从库设
super_read_only=ON,禁止一切写入 - ✅ 不要随便
reset sla ve和sql_sla ve_skip_counter - ✅ Binlog清理周期别太短,
expire_logs_days建议7~15天 - ✅ 大事务拆小,DDL避高峰
- ✅ 必备工具:
pt-table-checksum查差异、pt-table-sync修数据、SHOW SLA VE STATUSG看状态 - ✅ 监控告警:IO/SQL线程状态、延迟、磁盘空间、服务器资源
主从同步这东西,原理不复杂,但出问题的方式有无数种。说到底,大部分故障看起来是参数和SQL的锅,根子都是数据一致性烂了。把这个想明白,下次碰到报错就知道往哪使劲了。
你在配置主从的时候遇到过什么奇葩报错?或者面试被问过什么特别刁钻的问题?欢迎在评论区交流,互帮互助少踩坑。
本文案例基于 MySQL 8.0。主从复制配置因版本和环境不同略有差异,建议在测试环境先复现验证。
