一、问题/场景描述
在维护MySQL主从复制架构时,运维人员常常遇到复制中断并报错1062的情况。该错误表现为:在从库上执行show slave status命令时,Last_Error字段显示类似“Error ‘Duplicate entry ‘xxx’ for key ‘PRIMARY” on query. Default database: ‘dbname’. Query: ‘INSERT INTO table …’”的信息。这通常意味着从库尝试插入一条主键已存在的记录,导致复制进程停止。
二、原因分析
MySQL主从复制报错1062的直接原因是主库的binlog中包含了INSERT或UPDATE语句,而从库上对应的表中已存在相同主键或唯一索引的记录。根本原因可归纳为以下几类:
1. 从库被意外写入数据:从库被设置为读写模式(read_only=0),或者有应用直接向从库插入数据,导致主键冲突。
2. 主从数据不一致:由于网络延迟、异常重启或人为操作,导致从库上的数据与主库不完全同步,例如从库缺少部分数据但多出重复记录。
3. 半同步或异步复制的滞后:在高并发写入场景下,从库可能因复制延迟而未能及时应用binlog,此时若主库再次插入相同主键的数据,从库会报错。
4. 主键设计问题:若表使用自增主键,但主从自增步长配置不当,或主库重启后自增值回退,也可能引发冲突。
三、详细解决步骤
步骤1:确认错误详情和复制状态
首先登录从库,执行以下命令查看复制状态和具体错误信息:
mysql> SHOW SLAVE STATUSG;
重点关注 Last_Error、Last_SQL_Errno、Last_IO_Errno 字段。若Last_SQL_Errno为1062,则确认问题。
步骤2:跳过错误事务(临时恢复复制)
如果错误是偶发且数据一致性要求不高,可以临时跳过该错误事务,让复制继续。执行以下步骤:
mysql> STOP SLAVE;
mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
mysql> START SLAVE;
注意:此方法仅跳过一行错误,若错误连续出现,需重复操作。生产环境中应谨慎使用。
步骤3:定位并修复冲突数据
跳过错误后,需找出冲突行并手动修复。假设错误提示为“Duplicate entry ‘100’ for key ‘PRIMARY’”,查看从库表:
mysql> SELECT * FROM dbname.table WHERE id = 100;
若从库存在该记录而主库也有相同记录,则从库的该行可能是多余的。根据业务逻辑决定删除或更新:
mysql> DELETE FROM dbname.table WHERE id = 100;
若从库记录需要保留,则需在主库上修改对应行主键值,并重新同步。
步骤4:重新同步从库数据(彻底解决)
若错误频繁出现,说明数据不一致严重,建议重新同步从库。步骤如下:
# 在主库上导出数据(排除锁表影响)
mysqldump -u root -p --single-transaction --master-data=2 --databases dbname > /tmp/master_dump.sql
# 在从库上导入数据
mysql -u root -p < /tmp/master_dump.sql
# 重置从库复制
mysql> STOP SLAVE;
mysql> RESET SLAVE;
# 从dump文件中获取MASTER_LOG_FILE和MASTER_LOG_POS
grep "CHANGE MASTER TO" /tmp/master_dump.sql
# 重新配置复制
mysql> CHANGE MASTER TO MASTER_HOST='主库IP', MASTER_USER='repl', MASTER_PASSWORD='密码', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=123456;
mysql> START SLAVE;
步骤5:验证复制状态
再次检查从库状态:
mysql> SHOW SLAVE STATUSG;
确保 Slave_IO_Running 和 Slave_SQL_Running 均为 Yes,且 Seconds_Behind_Master 为0或较小值。
四、注意事项
1. 跳过错误事务仅作为临时恢复手段,不能解决根本问题,后续必须排查数据不一致原因。2. 在重新同步前,建议对主库进行全量备份,并确保从库没有写入操作(设置read_only=1)。3. 若使用GTID复制,跳过错误的方式不同(需注入空事务),请参考MySQL官方文档。4. 定期使用pt-table-checksum等工具检查主从数据一致性,防患于未然。
五、适用环境
本文适用于MySQL 5.7及以上版本,包括MySQL 8.0,在Linux(CentOS 7/8、Ubuntu 20.04)环境下测试通过。若使用MariaDB,部分命令可能略有差异。
