📌 今日关键词:主从同步失败、1032/1062、并行复制MTS、GTID、生产排障
大家好呀!我是 数据库小学妹 👋
前几篇我们聊了主从复制的搭建、监控,还讲了主从延迟怎么排查。有不少同学留言问:"小学妹,你说的这些我都配好了,但偶尔 Slave_SQL_Running 突然变 No,整个人都懵了,完全不知道从哪查起。"
说实话,我第一次遇到也懵过。那天线上从库查不到新数据,打开监控一看 Slave_SQL_Running: No,报错 Error_code: 1032,脑子里一片空白。折腾了一下午才修好,后来跟DBA前辈请教 + 翻官方文档 + 踩了几次坑,慢慢总结出一套路子。
今天就把我整理的 MySQL主从同步失败五大类高频诱因 分享出来,配上报错定位、底层原理和解决方案。面试被问"主从同步为什么中断",或者线上突然挂了要快速定位,翻这篇就够了。
一、数据层:最高频,面试必考
🔥 核心本质:主从数据不一致,从库回放 Binlog 时找不到目标行或发现重复数据。
1. 表没有主键/唯一索引(报错1032)
这是我踩的第一个坑。当时接手的库存日志表 tb_inventory_log,开发同学忘加主键了,表就这么裸着跑了两个月。开启并行复制 slave_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 SLAVE SQL_THREAD;
SET GLOBAL sql_slave_skip_counter = 1;
START SLAVE 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_slave_skip_counter 用太频繁了,跳着跳着一堆数据没同步。
③ 从库上跑了定时任务或报表,自己生成了主库没有的数据。
修法: 用 pt-table-checksum 检查数据差异,pt-table-sync 同步差异数据。严重的直接重做全量备份再恢复从库。
二、配置层:容易被忽视的隐藏炸弹
🔥 核心本质:主从库权限、sql_mode、字符集等配置不一致,从库解析不了主库的 Binlog。
1. 复制账号权限不够
Access denied for user 'repl'@'xxx' (using password: YES)
我刚学搭主从的时候就犯过——建了复制账号 repl,只给了 REPLICATION SLAVE 权限。结果主库执行 ALTER TABLE 改表结构,从库回放时因为缺 ALTER 权限直接挂了。
解决: 给复制账号开完整权限:
GRANT REPLICATION SLAVE, 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: '\xF0\x9F\x98\x82' 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 slave,清空了从库的 gtid_executed。恢复同步的时候,GTID 全乱了,只能重搭。
教训: 不要随便 reset slave!GTID 冲突的正确做法是 reset slave all 然后重新从主库拉 GTID。
3. RelayLog/Binlog 文件损坏
Corrupted relay log file 'xxx-relay-bin.000001'
磁盘满、突然断电、误删日志都可能导致这个问题。预防措施就两条:binlog_checksum=CRC32 开启校验,定期监控磁盘空间。
四、MySQL 8.0 并行复制(MTS)专属坑
开启了 slave_parallel_workers 之后性能确实上去了,但新坑也来了。面试特别喜欢问这个,用来区分你熟不熟 8.0。
1. 多线程事务冲突
多个 Worker 线程并行回放,恰好操作了同一张表的同一行,直接死锁。解决办法:slave_preserve_commit_order=ON,保证从库事务提交顺序和主库一致。slave_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_slave_skip_counter |
数据差异越积越多 | 应急才能用,用完必须对齐数据 |
误执行 reset master/slave |
同步链路直接断裂 | 禁止!操作前先备份 |
| 主库 Binlog 过期清理太快 | 从库消费不完日志就没了 | expire_logs_days 设 7~15 天 |
面试怎么答?
如果面试官问:"请说说 MySQL 主从同步失败的常见原因?"
我的回答套路:
主从同步失败主要分五类。第一是数据层,占比最高,核心是无主键导致 1032、主键冲突导致 1062、主从数据不一致。第二是配置层,权限不够、sql_mode 不一致、字符集不对,这些往往搭主从的时候就埋下了雷。第三是Binlog 参数,format 不一致、GTID 冲突、日志损坏。第四是 8.0 并行复制 MTS 的专属问题,多线程事务冲突、WRITESET 依赖检测失效。第五是人为操作,从库误写、频繁跳过事务、过早清理 Binlog——这其实是生产环境最高频的原因。
预防的核心就是四句话:主从配置保持一致、所有表加主键、从库禁止写入、规范运维操作。加上监控和告警,基本上能覆盖 90% 的问题。
📋 生产避坑清单
- ✅ 所有表必须有显式主键,MySQL 8.0.30+ 可用不可见主键
- ✅ 主从版本、sql_mode、字符集、binlog_format、GTID 开关完全统一
- ✅ 从库设
super_read_only=ON,禁止一切写入 - ✅ 不要随便
reset slave和sql_slave_skip_counter - ✅ Binlog 清理周期别太短,
expire_logs_days建议 7~15 天 - ✅ 大事务拆小,DDL 避高峰
- ✅ 必备工具:
pt-table-checksum查差异、pt-table-sync修数据、SHOW SLAVE STATUS\G看状态 - ✅ 监控告警:IO/SQL 线程状态、延迟、磁盘空间、服务器资源
主从同步这个东西,原理不复杂,但出问题的方式有无数种。说到底,大部分故障看起来是参数和 SQL 的锅,根子都是数据一致性烂了。 把这个想明白,下次碰到报错就知道往哪使劲了。
你在配置主从的时候遇到过什么奇葩报错?或者面试被问过什么特别刁钻的问题?评论区一起交流,咱们互帮互助少踩坑!💪
👋 我是 数据库小学妹,一个用设计师思维学数据库的转行人。增删改查、索引优化、主从复制、生产排障——这些我都是一步步踩坑踩过来的。关注我,陪你一起从小白到独当一面!
本文案例基于 MySQL 8.0。主从复制配置因版本和环境不同略有差异,建议在测试环境先复现验证。