先给出一个核心结论:在多源复制场景下排查特定通道的日志不同步问题,真正的难点不在于“能否发现问题”,而在于你是否使用了正确的命令、是否关注了错误的状态字段。许多运维人员之所以踩坑,往往是因为习惯了单通道复制时的操作方式,拿到SHOW REPLICA STATUS结果后只看了第一行就下结论,结果漏掉了真正出问题的通道。
因此,第一步必须明确是哪个通道,然后针对性地检查该通道的线程状态,而不是笼统地查看主状态。
查询指定通道的复制线程是否正常运行
多源复制架构中,每个主库对应一个独特的Channel_name,它们的状态彼此独立、互不干扰。如果还像单通道那样只执行一次SHOW REPLICA STATUS,默认只会返回第一个通道的信息,而恰好这个通道没有异常,另一个通道却已经阻塞了很长时间——这种情况在线上实际运维中非常常见。
关键在于,必须显式指定通道名称进行查询:
SHOW REPLICA STATUS FOR CHANNEL 'master1'\G
获取结果后,重点关注Sla ve_IO_Running和Sla ve_SQL_Running这两个字段,两者必须都是Yes才算正常。只要有一个是No,就说明该通道的中继链路已经中断,Seconds_Behind_Master这个数值基本上已经失去参考价值,无需再关注。
以下几个典型场景值得留意:
- Sla ve_IO_Running显示Connecting:大概率是网络不通、主库宕机或复制用户权限配置有误
- Sla ve_IO_Running显示No,并且Last_IO_Error中提示“error connecting to master”:此时需要检查主库的bind_address、防火墙规则,以及repl用户是否允许从当前IP地址登录
- Sla ve_SQL_Running显示No,Last_SQL_Error指向Duplicate entry或Table doesn‘t exist:这意味着SQL线程被某条DML或DDL语句卡死,只能人工介入处理
对比GTID集合是否持续收敛
如果开启了GTID模式,判断逻辑会更加清晰。Retrieved_Gtid_Set和Executed_Gtid_Set这两个值,正常情况下应该逐步趋近——一个在拉取,一个在执行,最终趋向一致。
如果两者长时间不相等,需要进一步分析:Retrieved_Gtid_Set不再变化,说明IO线程没有拉取日志,问题出在网络或主库端;反之,Retrieved_Gtid_Set持续增大但Executed_Gtid_Set卡住不动,则一定是SQL线程被阻塞了。
确认命令如下:
SELECT Channel_name, Retrieved_Gtid_Set, Executed_Gtid_Set FROM performance_schema.replication_connection_status WHERE Channel_name = 'master1';
具体解读:
- Retrieved_Gtid_Set为空或长时间不变 → IO层故障(主库没有新事务、网络断开、binlog被purge)
- Retrieved_Gtid_Set持续增大但Executed_Gtid_Set不动 → SQL层堵塞(从库缺少表、字段类型不兼容、触发器报错等)
需要特别注意:在GTID模式下,传统的sql_sla ve_skip_counter已经无法使用。想要跳过事务,必须使用SET GTID_NEXT配合空事务来操作,否则会直接破坏GTID序列,修复起来更加麻烦。
检查relay log是否写满或损坏
这是一个容易被忽略的细节:从库磁盘空间不足、relay log文件损坏,或者relay_log_space_limit设置过小,都可能导致IO线程静默失败——它不报错,但也不写入日志。具体表现就是Relay_Log_Space这个值不再增长。
先查看当前配置:
SELECT @@relay_log_space_limit, @@relay_log_purge;
- 如果relay_log_space_limit大于0且剩余磁盘空间不足以容纳该值,IO线程会自动暂停写入relay log
- 如果relay_log_purge设置为OFF,旧的relay log会逐渐积累,最终撑爆磁盘;通常建议保持ON(默认值)
- 想确认relay log文件是否完好,可以手动执行mysqlbinlog /var/lib/mysql/relay-log-bin.000001,如果报错则说明文件损坏,此时需要清空relay_log_index再重启复制
确认主库binlog是否被提前清理
这一条是排查链条中最隐蔽也最容易踩坑的环节。主库的expire_logs_days设置过短(比如只保留1天),某个通道因各种原因停顿超过这个周期,等从库再次连接时请求的Master_Log_File已经被主库purge掉。错误信息通常如下:
Got fatal error 1236 from master when reading data from binary log: ‘Could not find first log file name in binary log index file’
验证逻辑分为几步:
- 在从库上查询该通道当前的位点:SELECT Master_Host, Master_Log_File, Read_Master_Log_Pos FROM performance_schema.replication_connection_status WHERE Channel_name = ‘master1’;
- 然后登录主库执行SHOW BINARY LOGS,确认从库记录的Master_Log_File是否还在列表中
- 如果已经丢失,并且该通道启用了GTID,就需要对比主库的gtid_executed与从库的Executed_Gtid_Set,使用SET GLOBAL gtid_purged = ’xxx’补齐缺失集合——注意务必保证purged集合完全覆盖缺失部分,否则仍然会报错
- 如果是非GTID模式,则只能重建该通道:导出主库当前数据,获取新的binlog position,重新执行CHANGE MASTER TO … FOR CHANNEL
真正麻烦的不是发现不同步,而是发现时已经丢失了几天的日志。日常运维策略应该是:绝不要只盯着Seconds_Behind_Master,因为一旦通道中断这个数值就完全失效,毫无参考价值。真正需要关注的是Retrieved_Gtid_Set的增长趋势,以及主库binlog的存留周期——这两个字段才是多源复制环境下真正的“信号灯”。
