日常运维中,DBA经常会遇到MySQL 主从复制的错误,比如下图中,sql线程显示错误 HA_ERR_KEY_NOT_FOUND(错误码 1032),主从中断。这类错误通常是主从数据不一致引起的,修复成本较高,很多时候都需要重建从库。本文梳理了常见的几种原因和对应的解决方案。

常见原因
1、从库误操作
当从库有写入权限时,就无法避免误操作,经常遇到开发、运维同事不小心登录从库执行dml。
当开启GTID功能时,每个主机都会有自己的事务集,查看GTID写入集就可以轻松判断从库是否写入了数据。
#查看GTID,通过UUID观察是否是本地生成的事务集。
show master status;
解决方案:从库开启超级只读,杜绝误操作发生。
#开启超级只读
set global read_only=ON;
set global super_read_only=ON;
2、从库开启 event scheduler
默认情况下,创建event事件时,会默认DISABLE ON SLAVE选项。但是生产环境复杂多变,如主库切换,或者数据库迁移等场景都会导致event配置不可控。
#查看事件调度器状态
show variables like 'event_scheduler';
#检查复制是否正常
show slave status\G;
当从库事件调度器开启时,主库生成的事件通过binlog同步到从库后,从库可能会被重复执行(主库一次,从库一次)。当从库本地修改的数据与主库同步数据冲突时,破坏了复制一致性,引发报错。
解决方案:禁用从库事件
[mysqld] event_scheduler= OFF super_read_only=1 read_only= 1
3、复制过滤
配置复制过滤(如replicate-do-db、replicate-ignore-table等)可能导致主从数据不一致。基于语句的复制(SBR),过滤规则依赖use语句指定的数据库。
#若主库执行跨库操作,从库可能因过滤规则忽略该操作,导致数据不一致。
use db1;
update db2.table SET...
解决方案:使用replicate-wild-do-table匹配规则
change replication filter replicate_wild_do_table = ('db1.%', 'db2.%');
4、主键(索引)缺失
<1> 基于语句的同步
update/delete语句依赖where条件匹配。若无唯一索引,主从数据分布差异可能导致影响行数不同(如主库更新2行,从库更新3行),导致数据不一致;
<2> 基于行的复制
无主键或者索引缺失时,从库需全表扫描定位目标行,性能下降且可能误改重复行(所有列值相同时);
<3> 无显式主键时
InnoDB自动生成ROW_ID作为聚簇索引键。主从库的ROW_ID可能不同,在崩溃恢复等场景中引发意外行为。
解决方案:
避免从库修改表结构(从库开启只读);binlog_format强制使用row格式;显示定义主键;主从sql_mode保持一致,避免数据截断或插入行为不同等。
[mysqld]
# 从库开启只读
read_only=ON
super_read_only=ON
# 主从sql_mode保持一致
sql_mode= 'xxx'
# binlog_format为row格式
binlog_format=ROW
# 强制所有表必须指定主键
sql_require_primary_key=ON
5、参数配置不当
参数slave_rows_search_algorithms用于控制从库在应用binlog时如何定位数据行。当表缺少主键或者唯一索引,且指定算法为HASH_SCAN时存在哈希碰撞风险,这可能导致从库误更新/删除非目标行,造成数据不一致。
在MySQL 8.0中,HASH_SCAN算法在哈希冲突时(如多行crc32值相同),可能错误匹配行记录,导致从库复制报错(如Can’t find record)或数据错乱。一般情况下,没主键 + hash scan + MTS + replace into批量操作极容易引发报错。
解决方案:
所有表显示添加主键(无意义自增主键或业务主键);参数调优,禁用hash_scan算法。
[mysqld]
# 强制所有表必须指定主键
sql_require_primary_key=ON
# 禁用HASH_SCAN
slave_rows_search_algorithms=INDEX_SCAN,TABLE_SCAN
#自动为无主键表创建隐式主键,8.0.30引入
sql_generate_invisible_primary_key=ON
注:修改slave_rows_search_algorithms算法,需要重启复制线程生效。




