ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

MGR集群SEC节点ERROR状态排查与恢复实践指南

MGR集群SEC节点ERROR状态排查与恢复实践指南 开局先交代一个实操场景某天半夜告警群里连着弹出三条消息MGR集群的SEC节点状态从ONLINE掉成了ERROR监控图上一条血红的长线直接戳到天亮。当时第一反应不是急着重启而是先稳住主节点的写入流量然后把这个SEC节点的报错日志完整捞出来看了一遍。这篇东西就是对那次排障过程的完整复盘顺带把MGR集群里SEC节点常见的ERROR类型、根因定位方法、恢复操作流程都梳理出来方便以后遇到同类问题时能照方抓药。1. 问题现象与定位思路1.1 SEC节点ERROR的典型表现先说MGR里节点的状态机。一个SEC节点从启动到真正对外提供读服务会经历OFFLINE、RECOVERING、ONLINE几个状态每个状态转换都有对应的内部校验逻辑。ERROR状态通常意味着节点无法完成某个校验环节可能是数据的一致性校验没过、可能是与主节点之间的连接中断太久、也可能是认证状态过期导致无法重新建立复制通道。从监控上看节点状态变成ERROR的瞬间通常伴随三个信号一是组视图group view中该成员的状态列为ERROR二是主节点的错误日志里出现该节点对应的连接超时记录三是该节点的performance_schema.replication_group_member_stats表中事务认证失败次数开始递增。这三个信号不用等告警直接查就能确认问题范围是在连接层、复制层还是认证层。1.2 排障前的信息收集清单动手修复之前先把这几类信息抓齐能省掉大量瞎猜的时间当前的组视图状态SELECT * FROM performance_schema.replication_group_members;节点的复制通道状态SHOW REPLICA STATUS\G重点看Replica_SQL_Running_State和Last_SQL_Error该节点的事务认证统计SELECT * FROM performance_schema.replication_group_member_stats;主节点上最近的binlog文件列表SHOW BINARY LOGS;SEC节点的错误日志MySQL错误日志、系统journal日志都要看有些时候问题在操作系统层这五类信息收集齐了之后再对照下面几种常见错误场景去缩小范围基本不会跑偏。2. MGR集群中SEC节点的角色与实际负载2.1 SEC节点在MGR集群架构里的定位MGRMySQL Group Replication是一个基于Paxos协议实现的高可用集群方案集群成员角色分为PRIMARY主节点和SECONDARY从节点也就是标题里说的SEC节点。在企业真实的部署里SEC节点的任务并不只承担备份数据这种被动职责它还需要承担本地的读写分离流量、作为报告的查询底座、甚至在某些多主模式下参与写请求的处理。我见过不少团队把SEC节点当成一个备胎日常流量压上去之后SEC节点出现ERROR的频次会明显上升。原因在于SEC节点需要实时回放主节点同步过来的binlog事件而回放过程中一旦出现锁等待、大事务冲突、或者并行复制线程的协调异常就会在节点上留下ERROR痕迹。更进阶的误用方式是直接把SEC节点作为ETL任务的来源库全量扫描类的查询会把buffer pool搅动得很厉害直接影响复制回放线程的性能和稳定性。2.2 SEC节点ERROR状态的影响范围一个SEC节点的状态异常影响面经常被低估。首先直接受影响的是路由到该节点的读流量业务侧会收到连接失败或者查询超时的报错其次MGR集群的容错机制是基于多数派投票的如果集群只有三个节点其中一个SEC节点挂了剩下的主节点和另一个SEC节点还能维持集群可用但如果恰好主节点的心跳检测也出现抖动整个集群可能会进入不可写状态最后被标记为ERROR的节点如果长期不处理它积累的事务差距会持续增大后续恢复的成本会呈指数级上升。这也是为什么MGR的SEC节点ERROR纠错不能等等再看必须第一时间介入处理。3. SEC节点ERROR的常见类型与根因拆解3.1 连接层错误无法与主节点建立复制连接这类错误的日志特征比较典型SEC节点的错误日志里会出现Got an error reading communication packets或Timeout reading communication packets之类的记录背后的根本原因往往是网络分区、防火墙策略变更、或者主节点主动断开了连接。排查时先做两步基础检查确认group_replication_recovery通道的SSL配置主从是否一致确认主节点的max_allowed_packet与SEC节点是否匹配。我遇到过一个很隐蔽的案例主节点更新了SSL CA证书但SEC节点的recovery通道还在沿用老证书报错信息居然只是笼统的Authentication plugin cannot be loaded不抓包根本想不到是证书不匹配。3.2 认证层错误事务验证失败MGR的认证Certification机制是整个集群一致性的基石。主节点提交一个事务时会先做写入集的冲突检测然后把事务广播给其他节点做同样的认证。SEC节点报Certification failed类错误时首先要查的是performance_schema.replication_group_member_stats里的COUNT_TRANSACTIONS_CONFLICTS计数。高冲突场景多数出现在多主模式下两个节点同时写同一行数据单主模式下则多见于大事务与DLL变更时间窗口重叠。处理冲突事务的方式不要简单粗暴地跳过报错事务而是要把对应的事务内容提取出来分析它为什么在认证阶段被拒绝。很多时候根源是业务侧没有合理设计主键或者唯一索引导致认证阶段产生了大量误判冲突。3.3 数据层错误SEC节点与集群数据不一致SEC节点数据不一致是ERROR状态里最麻烦的一种。常见触发点包括主节点上有事务没写binlog就提交比如用了sql_log_bin0或者SEC节点在做增量追赶时发现主节点的binlog已经过期清理binlog被purge无法提供缺失的那段事务日志。最典型的场景是SEC节点长时间离线离线期间主节点的binlog超过了expire_logs_days/binlog_expire_logs_seconds的保留周期部分日志被清理。此时SEC节点即使网络恢复正常也无法通过常规复制通道补齐缺失数据日志里会出现The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION 1, but the master has purged binary logs的报错。3.4 说明一下MGR的节点行为机制和常见运维误区很多DBA第一次处理MGR节点的ERROR时习惯性地去STOP GROUP_REPLICATION然后START GROUP_REPLICATION寄希望于重启大法。这个操作本身不危险但它只能解决连接层面的瞬时抖动对数据不一致、认证冲突这类深层次问题毫无帮助反而会让节点在RECOVERING状态里反复横跳并可能因为反复全量恢复消耗大量CPU和网络带宽拖累其他节点的性能。正确做法是先判断节点与主节点的事务差距(gtid_executed的差集)再决定是用增量方式补数据还是干净利落地做一次全量重建这比盲目重启高效得多。4. 实操SEC节点状态检查与核心参数配置4.1 用SQL检查节点的实时状态把以下几条查询存成固定脚本每次处理SEC节点ERROR之前先跑一遍效率会高很多-- 查看集群成员状态 SELECT MEMBER_ID, MEMBER_HOST, MEMBER_PORT, MEMBER_STATE, MEMBER_ROLE FROM performance_schema.replication_group_members; -- 查看SEC节点的事务认证和同步情况 SELECT MEMBER_ID, COUNT_TRANSACTIONS_IN_QUEUE, COUNT_TRANSACTIONS_CONFLICTS, COUNT_TRANSACTIONS_REMOTE_IN_APPLIER, COUNT_TRANSACTIONS_LOCAL_PROPOSED, COUNT_TRANSACTIONS_LOCAL_RECEIVED FROM performance_schema.replication_group_member_stats; -- 查看SEC节点的复制通道状态 SHOW REPLICA STATUS\G -- 查看SEC节点当前已经执行的GTID集合 SELECT GLOBAL.GTID_EXECUTED; -- 查看主节点上GTID集合此查询在主节点执行 SELECT GLOBAL.GTID_EXECUTED;对比GTID_EXECUTED集合的差集能够直接判断数据缺口的大小。如果差集只有少量事务可以尝试让节点重新加入集群、走增量复制追赶如果差集巨大或者包含了已经被purge的事务那就别犹豫走全量重建流程。4.2 关键参数配置建议与依据MGR的两个参数在SEC节点上需要特别关注。第一个是group_replication_communication_stack这个参数决定了节点间通信走XCom还是走MySQL协议建议保持默认的XCom除非网络环境对组播支持极差否则不要轻易改第二个是group_replication_consistency这是一个容易踩坑的参数——如果把它设置成AFTER或者BEFORE_ON_PRIMARY_FAILOVER可以对一致性要求高的读请求提供更强保证但代价是增大事务处理延迟SEC节点在高写入负载下更容易在认证队列里积压进而触发ERROR状态。我在实际运维中建议对于大部分应用场景保持group_replication_consistency默认为EVENTUAL即可——MGR保证的是数据的最终一致性而不是强一致不要指望用一个参数让所有业务场景都完美。如果业务有更高的读一致性要求更好的思路是把这类读请求路由到主节点而不是让SEC节点承担超出能力范围的强一致负担。另外还要检查slave_parallel_workers的配置。很多SEC节点的ERROR问题源于并行复制线程数设置不合理设得太少大事务堆积会导致整个回放线程序列停滞设得太高在CPU核数不足的机器上反而引发频繁的线程切换开销。我一般从slave_parallel_workers4起步在压测观察后逐步上调同时配套设置slave_preserve_commit_order1避免小事务超车导致节点间commit顺序错乱。4.3 常见参数与推荐值对照表参数名推荐值设定说明group_replication_consistencyEVENTUAL严格控制这个参数的修改绝大多数读需求不需要强一致group_replication_communication_stackXCOM保持默认除非组通信遇到明确兼容性问题slave_parallel_workers4~8按CPU核数兼顾并行能力和稳定性不要盲目调大slave_preserve_commit_orderON防止MGR节点间提交顺序不一致binlog_expire_logs_seconds86400~604800太短会导致SEC节点离线恢复时binlog被提前purgegroup_replication_single_primary_modeON谨慎评估切多主多主模式的认证冲突率确实更高参数调整后通常不需要重启MySQL但要确认节点依然处于ONLINE状态修改后用SHOW REPLICA STATUS观察Replica_IO_Running和Replica_SQL_Running是否都为YES。5. 实操SEC节点ERROR的处理与恢复过程5.1 安全重置让SEC节点重新加入集群的常规操作流如果节点状态是ERROR但数据差距不大比如只有几十个事务的差距可以走标准重置流程-- 在SEC节点执行 STOP GROUP_REPLICATION; RESET SLAVE ALL; START GROUP_REPLICATION;执行完START GROUP_REPLICATION后节点会先进入RECOVERING状态此时重点观察SHOW REPLICA STATUS里Replica_IO_Running是否为YESperformance_schema.replication_applier_status_by_worker里是否有卡住的worker线程节点能否在预期时间内进入ONLINE状态如果节点在RECOVERING状态停留时间过长需要结合前面说的GTID差集判断是否要继续等待增量追赶。顺带提一个经验值增量追赶的速率受限于单个事务的大小以及SEC节点的磁盘IO能力如果长时间比如超过15分钟还卡在某个特定事务上优先检查那个事务是不是有大量的DDL或行级操作——这类事务在回放阶段很容易因为锁等待被卡住。5.2 全量重建数据差异过大时的可靠方案如果SEC节点的GTID差集过大或者缺的事务已经被purge那增量追赶这条路就走不通了。此时需要做全量数据重建。推荐做法是通过CLONE插件从主节点拉取数据快照或者用mysqldump恢复。用CLONE插件的流程如下在SEC节点执行INSTALL PLUGIN clone SONAME mysql_clone.so; SET GLOBAL clone_valid_donor_list 主节点IP:3306; CLONE INSTANCE FROM 复制账号主节点IP:3306 IDENTIFIED BY 密码;CLONE完成后SEC节点的数据目录会被替换成主节点的一致性快照此时还需要重新配置复制通道并启动MGR。提醒一下大家CLONE操作期间会短暂占用主节点的IO和网络资源尽量放在业务低峰期操作。mysqldump的方式适合数据量不大几十GB以内的场景mysqldump -h主节点 -u备份账号 -p --single-transaction --set-gtid-purgedON --all-databases --triggers --routines --events backup.sql恢复完成后记得不要手动执行RESET MASTER去清空GTID这个动作会破坏复制关系。直接启动group replication让节点自动补齐数据和状态。这条路径我已经走过很多次稳定性和耗时都优于手工核对GTID集合。5.3 节点恢复后的一致性验证节点重新加入集群并进入ONLINE状态后不能只看光鲜的状态标记还要做一轮验证工作比较SEC节点与主节点的核心表行数抽样结果查询performance_schema.replication_group_member_stats确认COUNT_TRANSACTIONS_IN_QUEUE归零在SEC节点上实际跑一遍只读查询确认延迟没有异常观察5~10分钟确认节点没有再次掉到ERROR状态6. 实操过程实录一次完整的SEC节点ERROR排障6.1 从告警到恢复的时间线记录这里记录一个比较典型的案例方便大家对照参考。某业务系统的MGR集群为三节点架构1主2备某天上午10点23分收到监控告警节点B的MEMBER_STATE从ONLINE变成了ERROR。当时业务侧已经出现读请求超时但主节点的写入未受影响。按照信息收集的流程我在10点25分先抓取了节点B的复制状态SHOW REPLICA STATUS\G输出里有一行很扎眼的报错Last_SQL_Error: Could not execute Write_rows event on table order_db.t_order; Cant find record in t_order, Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND同时主节点侧查询SHOW BINARY LOGS发现最早的binlog文件保留时间是最近8个小时。节点B上一次心跳记录已经是昨晚凌晨它离线了将近10个小时意味着它需要回放10小时的binlog事件而主节点只保留了8小时。6.2 根因确认与方案选择这个场景是典型的离线时间超过binlog保留周期导致的数据断档问题。节点B已缺失的事务包含在已经被purge的binlog文件里因此即便它和主节点之间的网络恢复正常也无法通过常规增量复制弥补缺口。这时的技术路线只有两条一是基于CLONE从主节点拉全量快照重建二是用mysqldump做逻辑备份恢复。考虑到业务不允许主节点长时间承受额外IO压力最终选择了在凌晨低峰期做CLONE重建并在当天白天临时将只读查询流量切换到另一个SEC节点C保证了业务侧的可用性。6.3 关键动作与操作细节凌晨1点开始执行CLONE方案。操作前先对主节点做了一次快速健康检查确认磁盘空间充足、没有长事务运行然后在节点B执行STOP GROUP_REPLICATION; INSTALL PLUGIN clone SONAME mysql_clone.so; SET GLOBAL clone_valid_donor_list 10.0.0.1:3306; CLONE INSTANCE FROM cluster_repl10.0.0.1:3306 IDENTIFIED BY 密码;CLONE执行过程约28分钟完成了约420 GB数据拷贝。等待CLONE完成之后节点B自动重启。重启完成后再执行START GROUP_REPLICATION;节点首先进入RECOVERING增量追上CLONE快照之后的主节点新事务总共用了大约5分钟然后切换为ONLINE状态集群整体恢复健康。6.4 复盘这次排障中有哪些可以复用的经验这次案例能沉淀出三条通用经验第一MGR集群的binlog保留策略要按节点最差离线场景来设计不能只看日常运行状态。如果按业务常态规划binlog_expire_logs_seconds为2小时SEC节点一旦离线超过2小时就只能全量重建。建议按节点最长可能离线时间至少2小时盈余来设定比如业务允许节点离线修复窗口是6小时那binlog至少保留8小时。第二节点的ERROR状态不全是技术故障大量是运维策略不匹配导致的。比如这个案例里问题本质是binlog保留时间与业务允许的离线修复窗口不匹配把binlog保留时长调上去之后类似的离线问题可以走增量追赶恢复成本大幅下降。第三优先把问题恢复方案固化到运维脚本里而不是每次临场翻手册。现在我的工单系统里预置了SEC节点ERROR标准化处理SOP信息采集→差距判断→增量或全量路径选择→执行→验证遇到同类问题直接触发SOP效率比手动排查高很多也更不容易漏步骤。另一次经验是老版本MGR的常见坑在对SEC节点做START GROUP_REPLICATION恢复时如果节点上配置了过期的hostname或report_host参数可能被集群误判为不同机器。建议提前确认所有节点的report_host配置都为各自稳定的IP或主机名避免因主机名解析波动导致节点反复ERROR。7. 常见问题排查速查表与避坑指引7.1 按报错特征速查问题定位报错日志特征问题层级优先排查方向1032: Cant find record数据层离线太久binlog被purge需全量重建1062: Duplicate entry数据层认证冲突检查业务写入模式及主键设计1253: Authentication requires secure connection连接/认证层SSL证书不匹配或过期双向核对证书Got an error reading communication packets连接层网络抖动/防火墙/负载均衡空闲断开Assertion failure in certify认证层版本兼容性问题优先统一小版本The master has purged binary logs数据层节点离线超时需要全量重建7.2 处理SEC节点ERROR时的三大禁忌禁忌一日志没看全就动手。不要因为告警面板显示ERROR就马上做节点重置。先花三分钟看MySQL错误日志和复制状态很多报错在日志里写得清清楚楚直接对上号了再决定操作路径。跳过这步可能把一个数据不一致问题误当成连接抖动执行了无效操作不说还多花了几倍的时间。禁忌二在主节点上执行RESET MASTER。处理SEC节点的数据缝隙时有些人习惯性地在主节点上执行RESET MASTER来简化GTID集合。这个操作会导致主节点开始新的binlog序列原本SEC节点缺失的事务彻底成为历史反而让所有需要增量追赶的节点都失去参照严重时只能全库重建。主节点的binlog是集群的心脏记录不能随便重置。禁忌三忽略业务峰值的复制延迟放大效应。如果SEC节点的ERROR问题已经导致它离线了一段时间恢复时它需要回放堆积的大量事务。如果直接在全天业务高峰的时刻做恢复SEC节点的回放线程会跟正常业务流量抢CPU和IO轻则恢复速度极慢重则把主节点拖到资源瓶颈。正确做法是评估数据缺口如果缺口很大宁可先保持SEC节点离线等低峰期再执行恢复操作。7.3 处理节点ERROR时常用的几个高风险判定点MGR的节点状态机和传统主从复制不一样它有一个系统自带多数派决策的机制在操作前需要判断当前集群的整体状态。如果当前集群只剩一个节点在线比如三节点集群挂了两个这时候对剩下的节点做重启或STOP GROUP_REPLICATION可能直接导致集群失去法定人数后续无法自动选主。遇到这种极端场景必须在维护窗口内快速恢复至少一个节点并且提前准备group_replication_force_members参数的正确写法防止人为造成整个集群的瘫痪。还有一个判定点很多新手容易踩坑对SEC节点执行CLONE或全量恢复之前一定要确认主节点的binlog中包含恢复节点所需的全部GTID。如果主节点也在近期做过数据清理即使CLONE了快照也无法满足后续增量衔接需要另找其他更全的数据源。8. 配套监控与日常预防方案8.1 在监控系统里加这几个必需的MGR指标很多团队的MySQL监控只覆盖了主从延迟和连接数对MGR节点状态缺乏感知导致SEC节点的ERROR往往是业务告警先于运维告警出现。至少要把以下指标纳入监控MEMBER_STATE变化事件节点从ONLINE掉到RECOVERING或ERROR时立即告警COUNT_TRANSACTIONS_IN_QUEUE队列积压超过阈值比如持续超过1000时提前预警COUNT_TRANSACTIONS_CONFLICTS冲突事务数开始攀升时往往是大事务或数据热点问题要出现的前兆Replica_SQL_Running_State的非ONLINE状态持续时长超过5分钟就告警这些数据都能从performance_schema中直接采集写个定时任务就能自动拉取。如果想省事也可以直接用MySQL Shell的AdminAPI来监控但底层数据源还是performance_schema。8.2 从架构层面降低SEC节点进入ERROR的概率监控治标架构治本。以下几个方面能显著减少SEC节点的ERROR频率第一合理设计节点的数据流。SEC节点不要同时承担复制回放重度OLAP查询ETL抽取三种角色资源竞争会让回放线程频繁抖动。如果业务确实有复杂查询需求单独拉一个分析型节点走binlog同步到其他OLAP引擎不要跟MGR的SEC节点混用。第二确认所有MGR节点的版本补丁一致。MySQL在小版本之间对MGR的状态机做过不少修正比如8.0.27版本对XCom的稳定性有明显改进8.0.33修复了部分认证场景下的泄漏问题。实践下来将集群统一到较新的小版本比实现更多业务功能更能减少ERROR相关的疑难杂症。第三严格约束大事务。MGR集群对超过1GB的单个事务容忍度很低这类事务在认证阶段和回放阶段都容易拖垮SEC节点。建议在业务写入源头设置事务规模限制或者在主节点上用max_binlog_cache_size做兜底配置。8.3 演练是预防体系里最容易被跳过的一环MGR集群的节点恢复操作如果只在真实故障时才第一次执行失败概率会明显偏高。我见过同行在真实故障时因为对CLONE插件的权限要求不熟悉前两次执行全部报权限错误白白浪费了故障恢复的黄金时间。建议每季度抽出维护窗口对SEC节点做一次主动的节点下线→数据校验→全量重建→重新加入集群演练把流程跑顺、把脚本调好真出事时才能做到胸有成竹。演练时还可以顺便测试一个很好的细节指标节点从发起重建到重新提供读服务的总耗时。把这个耗时记录下来作为后续判断是否值得增量修复还是直接全量重建的依据。比如某个环境里全量重建只要30分钟那增量修复超过30分钟就直接放弃修复走重建性价比高得多。9. 个人实操后的几点心得处理MGR的SEC节点ERROR表面上比拼的是SQL熟练度和参数懂得多不多实际上更考验对集群状态机的理解深度。MGR是一个分布式的状态机系统节点从ERROR到RECOVERING再到ONLINE每一步都需要满足前置条件判断条件和动作之间的因果关系是排障的关键。具备这种思维之后遇到再奇怪的ERROR状态第一反应不会是重启试试而是这个状态转换被哪个条件卡住了。另外别把全部精力都放在事后修复上。MGR集群的稳定性七分靠架构设计和容量规划三分靠应急处理能力。把binlog保留策略调好、把大事务治住、把监控阈值设准SEC节点进入ERROR的概率会直线下降。这比掌握一百条应急命令都更值钱。最后再分享一个实用的判断小技巧在处理SEC节点数据不一致问题时优先看mysql.gtid_executed表和binlog文件的间隙而不仅是看复制延迟。很多时候报错信息告诉你连接超时真正的根因却是数据断档只看表面报错会走不少弯路。先把GTID的关系理清楚绝大多数MGR节点恢复问题都变得清晰可解。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进