☰
MySQL主从同步中断排查与修复实战
2026/10/26 19:51:45 网站建设 项目流程

1. 问题背景:MySQL主从同步为何突然中断?

上周三凌晨2点15分,生产环境的MySQL从库突然报警,显示主从同步延迟超过300秒。作为DBA值班人员,我立即登录服务器检查状态。当时show slave status显示Slave_IO_Running=Yes但Slave_SQL_Running=No,错误信息提示"Could not execute Write_rows event on table db.order; Duplicate entry '178293' for key 'PRIMARY'"。

这种情况在电商大促期间并不罕见,但这次异常发生在业务低峰期,且主库没有明显的批量操作。更奇怪的是,这个主键冲突的记录在主库根本不存在!这让我意识到问题可能比表面看起来更复杂。

2. 排查路线图:从表象到根源的六步分析法

2.1 第一步:验证基础同步状态

首先确认基本同步参数是否正常:

SHOW VARIABLES LIKE 'server_id'; SHOW VARIABLES LIKE 'log_bin'; SHOW VARIABLES LIKE 'binlog_format';

发现从库的server_id居然与主库相同!这是第一个严重配置错误。虽然这不会直接导致主键冲突,但会导致网络分区时出现脑裂风险。立即用SET GLOBAL临时修改,并在my.cnf中永久修正。

2.2 第二步:解析冲突的relay log

通过mysqlbinlog工具分析出问题的relay log:

mysqlbinlog --base64-output=decode-rows -v /var/lib/mysql/relay-log.000123

在position 471238位置发现了可疑的INSERT语句。该语句试图插入主键为178293的记录,但主库binlog中根本没有对应记录。这说明有"幽灵事件"混入了同步流。

2.3 第三步:GTID一致性校验

启用GTID跟踪后发现更诡异的现象:

SHOW GLOBAL VARIABLES LIKE 'gtid_mode'; SELECT * FROM mysql.gtid_executed;

从库的gtid_executed表中存在一组不属于主库任何binlog的GTID(例如:a1b2c3d4-5e6f-7890-1234-567890abcdef:10000-15000)。这些"凭空出现"的事务正是导致冲突的元凶。

3. 深度分析:relay log污染的三重可能

3.1 可能性一:人为误操作

检查操作日志发现,有开发人员曾执行过:

STOP SLAVE; SET GLOBAL sql_slave_skip_counter=10; START SLAVE;

这种暴力跳过错误的方式会破坏GTID连续性。更糟的是,该开发人员随后手动执行了数据修复脚本,这些操作被误记入从库的binlog(log_slave_updates=ON),形成污染源。

3.2 可能性二:网络分区导致的事件重复

在故障时间点,监控显示网络有3次30秒左右的闪断。MySQL 5.7的自动重连机制可能导致部分事件被重复传输。通过比对主从binlog的checksum值确认了重复事件的存在。

3.3 可能性三:备份恢复的副作用

排查发现,一周前做过从库的物理备份恢复。当时使用xtrabackup重建时,未正确清理原有的relay log文件,导致旧事件与新事件混合。这解释了那些"幽灵GTID"的来源。

4. 修复方案:五步完整恢复流程

4.1 第一步:建立数据基准点

在主库锁定相关表后,执行:

FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS;

记录下File和Position值,同时在从库用mysqldump导出冲突表的结构和数据,形成恢复基准。

4.2 第二步:彻底重置复制环境

在从库执行完整清理:

STOP SLAVE; RESET SLAVE ALL; RESET MASTER; PURGE BINARY LOGS BEFORE NOW();

删除所有relay log文件:

rm -f /var/lib/mysql/relay-log.*

4.3 第三步:重建复制链路

使用正确的GTID自动定位方式重建复制:

CHANGE MASTER TO MASTER_HOST='master_host', MASTER_USER='repl_user', MASTER_PASSWORD='password', MASTER_AUTO_POSITION=1;

4.4 第四步:数据一致性校验

使用pt-table-checksum进行全量校验:

pt-table-checksum --replicate=test.checksums h=master_host,u=check_user pt-table-sync --replicate test.checksums h=master_host,u=sync_user --print

对差异数据生成修复脚本,经审核后执行。

4.5 第五步:防护措施加固

修改配置防止问题复发:

[mysqld] slave_parallel_workers=4 slave_parallel_type=LOGICAL_CLOCK sync_relay_log=1 sync_relay_log_info=1 slave_preserve_commit_order=1

5. 经验总结:主从同步的七个必知必会

  1. GTID使用铁律:任何情况下都不要手动设置sql_slave_skip_counter,应该通过注入空事务处理冲突

  2. 备份恢复规范:使用xtrabackup重建从库时,必须添加--slave-info参数并清理旧relay log

  3. 网络隔离防护:配置master_retry_count和master_connect_retry控制重试行为

  4. 监控关键指标:除了Seconds_Behind_Master,还要关注Exec_Master_Log_Pos的推进情况

  5. 权限最小化:回收开发人员的STOP SLAVE权限,通过中间件控制

  6. 日志保留策略:主库binlog保留7天以上,从库relay log至少保留3天

  7. 定期校验机制:每周用pt-table-checksum做全量校验,关键业务表每天校验

这次事故的根本原因在于多重防护措施被绕过。事后我们建立了复制环境变更的checklist,任何涉及复制的操作都需要双人复核。同时优化了监控系统,当检测到server_id冲突、GTID断层等异常情况时,会自动触发告警并锁定复制账户。

关键教训:主从同步不是"配置完就忘"的服务,需要像对待数据库核心服务一样进行日常监控和维护。每次异常处理都应该形成闭环,把临时解决方案转化为长期防护机制。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询