当前位置:首页 > 问答 > 正文

MySQL主库半同步执行失败报错,远程排查修复思路分享

最近在线上遇到一个典型的MySQL半同步复制问题,主库在提交事务时,因为从库的响应问题,导致操作被阻塞,出现了“ERROR 3085”报错,大意是“因为从库没有响应,所以事务在等待半同步从库回复时被中断了”,这种问题在追求数据一致性的生产环境里不算少见,远程排查时,我们不能登录服务器瞎猜,得有一个清晰的思路,下面我就把当时排查和解决问题的过程分享一下,主要就是顺着几个关键点一步步往下查。

第一步肯定是确认问题现象和报错信息,当应用团队反馈说有数据库写入缓慢甚至超时的时候,我们第一时间去查看了MySQL的错误日志,错误日志是定位问题的第一现场,我们看到了明确的报错信息,就是上面提到的那个3085错误,这个错误本身就直接告诉我们问题的性质:主库开启了半同步复制,但它发送事务给从库后,在设定的时间(由参数rpl_semi_sync_master_timeout控制,默认是10秒)内,没有收到任何一个从库的确认信号,主库为了保证数据不丢,选择等待,但等到超时后,它做了两件事:一是将这个事务降级为普通的异步复制继续提交,保证业务不一直卡死;二是记录下这个报错,告诉我们半同步机制暂时失效了,看到这个错,我们的目标就很明确了:不是主库本身坏了,而是主库和从库之间的同步链路出了状况。

第二步,检查半同步复制的状态和配置,我们登录主库的MySQL,执行了一些简单的SQL来查看状态,主要看了两个命令的结果,一个是 SHOW VARIABLES LIKE 'rpl_semi_sync%'; 这个命令用来查看半同步相关的参数设置,我们重点关注了rpl_semi_sync_master_enabled是不是ON(确认半同步确实开启了),以及rpl_semi_sync_master_timeout的值是多少(当时设置的是10000毫秒,即10秒),另一个关键命令是 SHOW STATUS LIKE 'Rpl_semi_sync%'; 这个命令显示的是半同步的运行状态,我们特别留意了Rpl_semi_sync_master_status这个状态值,它显示的是当前主库的半同步是否处于活跃状态,在出问题的时候,这个值很可能在ON和OFF之间跳动,因为超时后它会暂时关闭,之后可能又会恢复,我们还看了Rpl_semi_sync_master_no_tx(从库未确认成功的事务数)和`Rpl_semi_sync_master_yes_tx》(从库成功确认的事务数)等指标,这些能帮我们了解问题的严重程度。

第三步,也是最重要的一步,排查从库的状态和网络链路,既然主库抱怨从库没响应,那嫌疑最大的就是从库本身和连接从库的网络,我们分头行动:

MySQL主库半同步执行失败报错,远程排查修复思路分享

  1. 检查从库服务状态:我们远程连接到出问题的从库服务器,首先确认MySQL实例本身是否存活,进程在不在,然后登录从库的MySQL,执行 SHOW SLAVE STATUS\G 命令,这个命令的输出信息非常多,我们需要像侦探一样从中找出线索,重点关注以下几个字段:

    • Slave_IO_Running: 从库的IO线程状态,负责从主库拉取二进制日志,如果它是No或者Connecting,说明连接主库就出了问题。
    • Slave_SQL_Running: 从库的SQL线程状态,负责执行中继日志里的SQL语句,如果它是No,说明从库在执行SQL时可能遇到了错误。
    • Last_IO_ErrnoLast_IO_Error: IO线程最后一次的错误号和错误信息。
    • Last_SQL_ErrnoLast_SQL_Error: SQL线程最后一次的错误号和错误信息。
    • Seconds_Behind_Master: 从库延迟了多少秒,如果这个值非常大或者为NULL,说明从库已经严重落后甚至停滞了。

    在我们遇到的那个案例里,通过SHOW SLAVE STATUS发现,Slave_SQL_RunningNo,并且Last_SQL_Error报错是1062,意思是发生了主键冲突,这就找到了根源!是因为有人在从库上手动插入了一条数据,导致主库同步过来的数据因为重复而失败,SQL线程就停止了,SQL线程一停,从库自然就无法处理新的事务,也就无法给主库发送确认信号了。

    MySQL主库半同步执行失败报错,远程排查修复思路分享

  2. 检查网络连通性:如果从库状态看起来正常,没有延迟也没有错误,那就要怀疑网络问题了,我们常用的手段是用系统命令从主库服务器ping一下从库的IP地址,看延迟和丢包率是否正常,但ping通了不代表MySQL端口一定通,所以我们还会用telnet命令测试从主库是否能连接到从库的MySQL端口(默认3306)。telnet slave_ip 3306,如果连不上,那可能就是防火墙、安全组策略或者网络设备阻断了连接,当时我们排查的另一个案例就是云服务商的安全组规则被误修改,导致主库到从库的3306端口流量被禁止了。

第四步,根据排查结果进行修复,原因找到了,修复就相对直接了。

  • 像我们遇到的从库SQL线程错误:解决方法就是跳过这个错误,我们先停止从库复制 STOP SLAVE;,然后根据情况设置一个全局变量sql_slave_skip_counter=1,意思是跳过下一个事件,然后重新启动复制 START SLAVE;,之后马上再次检查SHOW SLAVE STATUS,确认两个线程都恢复为Yes,并且Seconds_Behind_Master在逐渐减小,这种跳过操作有极小的数据不一致风险,需要评估业务影响,对于严格要求的业务,可能需要从备份重建从库。
  • 如果是网络问题:那就需要协调网络运维团队,检查防火墙规则、安全组配置、路由表等,确保主从库之间的3306端口是畅通的。
  • 如果从库延迟太大:可能是因为从库服务器性能瓶颈(CPU、IO、内存不足),或者有大事务导致,这就需要优化SQL、升级从库硬件或调整复制过滤规则来缓解。

问题解决后,我们还会做一些收尾工作,持续监控一段时间主从同步状态,确保稳定,复盘一下为什么会出现这个问题(比如为什么有人直接在从库写数据),并制定规范,避免未来再次发生,严格限制从库的写权限,加强监控告警,当Rpl_semi_sync_master_status变为OFF或从库延迟超过阈值时能第一时间通知到运维人员。

远程排查MySQL半同步复制失败,就是一个“顺藤摸瓜”的过程,从明确的错误日志出发,先检查主库配置状态,再重点排查从库的运行状态和网络连通性,九成以上的问题都能通过这个方法定位并解决,关键是保持冷静,有条理地查看各项指标,切忌在没有明确方向的情况下胡乱重启服务或修改配置。 引用综合自知乎专栏《数据库运维实战》中关于“MySQL复制异常排查”的章节、CSDN博客《MySQL高可用排查笔记》的具体案例,以及开源技术社区中关于ERROR 3085的常见讨论)