
主从复制相关问题是面试中的高频面试题,而哪些场景会引起主从复制异常呢?
今天就遇到了一种主从复制中断的情况(SQL线程中断),查看日志报错是典型的1032错误,遇到这种开启别急着跳过事务!这可能是MySQL8.0并行复制与无主键表共同埋下的“定时炸弹”。本文带你深挖根源,从Binlog机制到Hash冲突,彻底解决这一顽疾。
一、异常现象
监控告警突然响起MySQL从库的SQL线程挂了。查看SHOW SLAVE STATUS,一行刺眼的报错映入眼帘:
Worker 1 failed executing transaction ...
Could not execute Update_rows_v1 event on table testdb.tb1;
Can't find record in '
tb1
', Error_code: 1032;
handler error HA_ERR_KEY_NOT_FOUND典型的1032错误。意思是:主库发来一条更新指令,但从库在表里翻遍了也找不到这条记录。
很多DBA的第一反应是:“数据不一致嘛,跳过这个事务不就行了?”
慢着!如果你只是简单地使用sql_slave_skip_counter跳过,可能只是治标不治本。更有趣的是,报错的是Worker 1,这意味着你开启了并行复制。在MySQL8.0环境下,结合“无主键表”这一特征,这背后隐藏着一个更深层的机制陷阱。
二、为什么会找不到记录?
1032错误的字面意思是“找不到记录”,但在MySQL8.0的并行复制场景下,原因远比“被误删了”要复杂。
1. 直接原因:数据不一致
最直接的可能性是,这行数据在主库存在,但在从库被误删了(比如有人手抖在从库执行了DELETE,或者之前的某个事务同步失败)。当主库发来UPDATE指令时,从库拿着“更新前的镜像”去比对,发现查无此人,于是报错。
2. 根本原因:无主键表的“大海捞针”
报错的表tb1没有主键。主键是数据库用来快速、准确定位一行数据的“身份证号”。没有主键,从库在重放数据更新时,就只能进行低效且不可靠的“大海捞针”。
在binlog_format=ROW模式下,Binlog记录了行变更的完整前后镜像。
3. 隐形杀手:MySQL8.0的Hash Scan算法缺陷
这是MySQL8.0的“坑”之一(或者说是一种策略)。为了优化无主键表在并行复制下的全表扫描性能,MySQL8.0引入了HASH_SCAN算法。
机制:它计算表中每一行数据的CRC32校验和,建立哈希映射来快速定位。
风险:如果表数据量大且没有主键,极易发生哈希冲突(不同的数据算出了相同的CRC32值)。一旦冲突,从库的SQL线程就会“看走眼”,要么匹配错行(比如多删除或更新),要么直接判定找不到行(被之前的操作处理或者匹配不上),从而抛出1032错误。
三、Binlog参数:是敌是友?
很多同学在排查时会问:这和Binlog参数有关吗?答案是:密切相关。
参数名 | 作用 | 推荐值 | 影响说明 |
|---|---|---|---|
slave_parallel_workers | 并行复制工作线程数 | 4-16(根据CPU 核数) | >0启用并行复制,问题触发的前提条件 |
slave_parallel_type | 并行复制类型 | LOGICAL_CLOCK(8.0默认) | WRITESET模式下冲突检测更严格 |
binlog_format | 二进制日志格式 | ROW | 基于行复制是无主键问题的核心场景 |
binlog_row_image | 行镜像记录内容 | FULL | MINIMAL模式会减少定位所需信息,加剧问题 |
require_table_primary_key_check | 表主键检查 | ON(8.0.20+) | 强制检查无主键表,提前发现问题 |
transaction_write_set_extraction | 事务哈希提取 | XXHASH64 | WRITESET模式必需,用于冲突检测 |
binlog_transaction_dependency_tracking | 依赖关系跟踪 | WRITESET(8.0.26+推荐) | 提高并行度,但无主键表会失效 |
关键参数说明:
四、如何优雅地填坑?
面对这种情况,不要慌张,按以下步骤操作:
1. 临时止血(恢复业务)
如果业务不能停,可以先临时跳过错误,或者开启幂等模式。
-- 方法A:开启幂等模式(仅建议在 ROW 格式下临时使用)
SET GLOBAL slave_exec_mode = 'IDEMPOTENT';
START SLAVE;
-- 方法B:如果是 GTID 模式,精准跳过该事务
STOP SLAVE;
SET GTID_NEXT='1ce64ba5-716d-11ef-8a7f-fa163eeec86c:1196639450';
BEGIN;COMMIT;
SET GTID_NEXT='AUTOMATIC';
START SLAVE;2. 定位问题
确认报错的表是否真的没有主键。
SHOW CREATE TABLE testdb.tb1;同时,检查主库该条记录是否存在,确认是否发生了数据不一致。
3. 根治方案
给表加上主键!给表加上主键!给表加上主键!
这是解决此类问题的唯一长久之计。
ALTER TABLE testdb.tb1 ADD COLUMN id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY;踩坑!MySQL这个参数让应用直接崩了,90%的DBA都忽略了!
如果有勇士敢于设置,那可以在配置文件中设置sql_generate_invisible_primary_key=ON,MySQL会自动为无主键表生成一个隐藏的row_id,既能满足复制需求,又不影响业务SQL。
4. 数据修复
加上主键后,建议重建从库,或者使用pt-table-sync工具进行主从数据一致性修复,确保从库不再因为“找不到行”而报错。
五、总结
MySQL8.0的并行复制虽然提升了性能,但也对表结构设计提出了更高的要求。
1032错误不仅仅是数据不一致的信号,更是表结构缺陷的警报。在MySQL8.0中,无主键表就是并行复制的“地雷”。请检查你的数据库,消灭所有没有主键的表,这才是DBA的自我修养。
大家还遇到哪些情况导致主从复制中断的情况呢,欢迎留言区讨论~~~