☰
PolarDB只读节点不可用排查指南:从症状到根因的完整路径
2026/10/6 13:53:26 网站建设 项目流程

开年第一个工作日,凳子还没坐热,告警群就炸了。业务方甩过来一张截图,只读库连不上了,报表全部超时。看了一眼工单标题,PolarDB从节点不可用,心里咯噔一下,这个开年“丢人”事故算是躲不掉了。

PolarDB的从节点,也就是官方叫法里的只读节点,在云原生数据库架构里地位很微妙。它不像自建MySQL从库那样,简单stop slave、start slave就能救回来,也不一定是数据同步坏了。很多老DBA会习惯性地用传统主从复制那套经验去排查,结果越查越蒙。这篇复盘,我就把整个排查过程拆成一套能照着抄的路径,从症状判型、架构原理、排查步骤到三个真实案例,一次讲透。无论你是刚接手PolarDB的运维,还是已经被只读节点折腾过几回,都能找到对应的解法。

1. 先搞清楚“从节点不能用”到底是个什么症状

接到告警别急着连上去看。先问三句话:什么业务受影响,从什么时候开始,监控报的是什么指标。这三句话决定了整个排查方向。

1.1 三类典型表现

PolarDB只读节点不可用,外在表现大致分三种,每种背后的原因完全不同。

外在表现可能原因排查重点
连接被拒、连接超时、报Too many connections节点健康检查失败被负载均衡摘除、连接数打满、节点重启中节点状态、连接数、健康检查日志
能连上,但SQL全部卡住、CPU打满、查询排队大查询占满CPU、锁等待、存储IO异常进程列表、慢日志、事务列表
能连上,但读到的数据严重滞后复制延迟、复制中断、大事务阻塞复制状态、延迟监控、大事务排查

第一种表现最像“不可用”,业务第一时间感知到的就是连不上。连接被拒不一定代表数据库进程挂了,很可能是PolarDB感知到该节点不健康,自动把它从集群地址中摘除了。第二种表现最迷惑,节点状态显示运行中,但业务实际访问已经超时,这时候需要登录节点看内部状态。第三种表现最容易被误判为“数据错了”,其实是延迟问题,读到的还是老数据。

1.2 影响范围界定

收到“从节点不能用”的反馈,第一件事是确认业务的访问路径。PolarDB集群通常有三种地址:主地址、集群地址、只读地址。主地址只指向主节点,集群地址和只读地址会做只读流量的负载均衡,把请求分发到所有可用的只读节点上。

如果业务用的是只读地址或集群地址,PolarDB会自动摘除不健康的只读节点,其他节点继续扛流量,业务可能只有部分请求失败。如果整个集群只有一个只读节点且它挂了,那所有只读流量都会失败,影响直接被放大。如果业务出于某种原因在代码里配置了到某个只读节点的“直连地址”,那就更惨,节点一挂,这个连接就彻底断了,没有任何容错。

先搞清楚影响范围,再决定止损动作。多数情况下,先把读流量切回主地址或临时摘掉故障节点,让业务恢复,比闷头查问题更重要。这也算是我丢过几次人之后总结出来的优先级:先止损,再定位。

2. 为什么说PolarDB从节点故障和自建MySQL主从完全不是一回事

如果还用自建MySQL主从的逻辑去处理PolarDB,很快会发现各种操作“使不上劲”。根本原因在架构。

2.1 一写多读架构与共享存储

自建MySQL主从是典型的一主一从或多从架构,主库把binlog推给从库,从库通过SQL线程回放,数据是“算”出来的,每一份存储都在各自身上的磁盘上,主备天然有两份数据副本。而PolarDB是共享存储架构,主节点和只读节点连的是同一份分布式存储,数据本身只有一份。

主节点产生的redo日志,通过物理复制同步给只读节点,只读节点不需要重新执行一遍完整的SQL逻辑,只需要把redo应用到自己本地的缓存和内存结构中。这意味着,只要存储没坏,从节点与主节点的数据不会出现“某张表没同步”这种传统复制里常见的分叉问题。从节点相对主节点,更像一个“共享数据的热缓存”。

这个架构带来的第一个排查思路变化是:如果从节点数据不对,优先怀疑的不是同步逻辑坏了,而是延迟没追上,或者读取路径出了问题。

2.2 复制机制差异带来的排查思路变化

传统主从里,从库慢往往是因为IO线程或者SQL线程卡住,回放速度跟不上主库写入,解决办法通常是调整并行复制参数、拆分大事务、优化无主键表。

PolarDB的物理复制走的是底层redo日志,效率远高于binlog逻辑回放。但它也有自己的软肋。只读节点自己是有内存和本地临时存储的,大查询、大排序、临时表都会消耗只读节点的本地资源。一旦只读节点的CPU或内存被一个慢查询拖垮,redo日志的应用也会被拖慢,表现就是复制延迟持续上涨,涨到一定阈值,PolarDB可能判定该节点不健康。

所以在PolarDB里,修复从节点复制延迟的思路,不是重新拉齐位点,而是先解决只读节点上正在跑的“坏查询”。这也是很多新手最容易转不过弯来的地方。

2.3 先别急着干三件事

下面三件事,我在排查PolarDB从节点故障时,一开始都干过,后来发现要么没用,要么有风险。建议先忍住。

注意:不要一上来就执行STOP REPLICA/START REPLICA。PolarDB只读节点的复制状态由云平台管控,手动启停复制线程可能和管控侧状态机冲突,一旦管控感知不到节点心跳,可能会触发自动重建节点流程,问题反而变复杂。

不要一上来就重启只读节点。重启一个看起来“状态异常”的节点,效果和拔插头一样,治标不治本。如果节点底下有坏盘或者内存问题,重启后很快就会复发。

不要一上来就删了重建。创建新只读节点需要全量初始化,如果一个几十TB的实例,创建过程可能要数小时。这段时间业务完全没有那个节点可用,损失更大。

正确打开方式是先做诊断,搞清楚节点当前处于什么状态,再决定是等它自愈、提规格、还是重建。

3. 从节点不可用的十大原因排查清单

把我在实际运维中遇到的从节点异常原因汇总了一下,不算特别全,但覆盖了大多数场景,开年到现在我已经靠这张清单避开了至少三次误判。

3.1 存储与容量

共享存储不代表没有容量问题。只读节点在查询过程中会产生临时表、排序文件、内部临时结果集,这些数据会落在只读节点各自的临时存储上。如果某个只读节点上经常跑重聚合查询,临时空间消耗会非常快。临时空间满了之后,查询会直接报错,现象就是只读节点上的SQL大面积失败。

控制台里能看到每个只读节点的存储水位。别只盯着集群总存储用量,要按节点维度看。节点各自的临时空间一般不会自动扩容,属于日常巡检最容易漏掉的项目。

3.2 复制延迟与大事务

PolarDB监控面板里有“只读节点复制延迟”这个指标,单位通常是秒。延迟抖动在业务高峰期比较常见,几十秒之内一般无感。但如果延迟持续上涨且没有回落趋势,说明只读节点正在被某个大操作卡住。

最常见的大操作有几种:无主键大表的一次全表更新、一条SQL涉及几千万行的批量修改、一个长时间运行的DDL。这些操作在主节点上可能只影响那一条SQL,但在只读节点上,redo应用会被阻塞,最终表现为复制延迟越来越大,业务读到的数据越来越旧,直到告警阈值触发。

3.3 规格变更与节点生命周期

节前扩容、节后缩容,是开年最常见的从节点故障诱因。PolarDB的规格变更,比如从4C8G升到8C16G,往往需要迁移节点到新的计算资源上,这个过程中节点会进入“变更中”状态,健康检查可能短暂失败,如果变更耗时较长,管理侧可能直接标记节点不可用。

还有一种情况是同时进行多个运维操作。比如一边在缩容只读节点,一边又触发内核小版本升级,两个操作之间没有做好等待,很容易导致节点状态卡在一个中间态。如果碰到这种情况,不要反复点击“重试”,先看变更任务的历史记录,确认当前卡在哪一步,再决定是否终止任务。

3.4 连接层与健康检查

只读节点“不可用”不等于数据库挂了,可能是健康检查失败被摘除了流量。PolarDB对只读节点有一套探测机制,如果节点长时间无响应、查询超时、或内部状态异常,它会被标记为不健康,从服务列表里摘掉。

摘除之后,业务连接池里的旧连接可能还指向这个节点,新连接会绕开它,于是出现“部分请求失败、部分请求正常”的诡异现象。排查时看控制台里该节点是否显示“不可用”或“维护中”,如果显示不可用但节点进程还活着,多半是健康检查探测失败,需要从业务侧排查是否有锁表、死循环、高CPU占用。

3.5 内核小版本与参数不一致

PolarDB控制台可以给整个集群设置参数模板,但如果有节点是后来单独创建的,或者某个节点经历过手工参数修改,就可能出现同一集群内不同只读节点参数不一致的情况。比如一个节点long_query_time是1秒,另一个是10秒;一个节点的max_connections是2000,另一个是200。这种不一致在平时没有明显问题,一旦遇到突发流量,小参数节点先扛不住,表现就是只读节点里的“单点故障”。

我在实际维护中踩过这个坑,最后养成了习惯:每次给集群调整参数后,都会逐个检查所有只读节点的参数值是否同步,尤其是新扩容节点加入集群之后,必须核对参数模板版本。

4. 实操排查:从接到告警到定位问题

下面是一条我自己验证过多次的排查路径,照着走,可以比较快地定位PolarDB从节点不可用的原因。整个过程不需要特别多的“神仙工具”,用好控制台和几条SQL就够了。

4.1 先看控制台三张图

任何一次从节点故障诊断,我都是先打开控制台的三张监控图:节点状态、复制延迟、CPU/内存/IO使用率。

节点状态图看的是当前从节点是否处于运行中、变更中、异常中。如果状态直接是异常,后面所有诊断都会轻松很多,因为问题大概率出在节点本身的资源或生命周期上。

复制延迟图很关键,尤其要把时间轴拉长,看延迟是从哪个时间点开始上涨的。延迟上涨点往往就是业务变更点,比如某条批量任务启动、某个表结构变更执行、某次大促流量开始。

CPU/内存/IO使用率关注的是趋势而不是瞬时值。只看某一瞬间可能什么都看不出来,但拉长到故障前后一个小时,就能看到到底是哪个资源先被耗尽,这通常就是根因。

4.2 登到只读节点看复制状态

控制台看完了,再登到只读节点上验证。PolarDB MySQL版兼容MySQL生态,所以很多熟悉的命令依然可用。

-- 查看复制状态(MySQL 8.0.22及以上语法) SHOW REPLICA STATUS\G;

重点看几项:Replica_IO_Running是否为Yes、Replica_SQL_Running是否为Yes、Seconds_Behind_Source的具体数值。在PolarDB的只读节点上,复制线程的概念和传统主从不完全一样,但这两个字段仍然能反映大致的健康状态。

再看一下当前进程列表,有没有一堆堆积的查询:

SHOW PROCESSLIST;

如果State里大量是“Waiting for table metadata lock”“Sending data”“Copying to tmp table”,那基本说明只读节点内部有查询在拖后腿。Sending data不一定是坏查询,但如果同一个SQL出现几十次,它占用的CPU一定不小。

4.3 抓出拖垮从节点的长事务

如果复制延迟高,下一步就要看事务列表。information_schema里的innodb_trx表,是排查长事务的第一现场。

SELECT trx_id, trx_state, trx_started, TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS trx_age_seconds, trx_mysql_thread_id, LEFT(trx_query, 100) AS trx_query FROM information_schema.innodb_trx ORDER BY trx_started ASC LIMIT 20;

这个SQL能按开始时间从早到晚列出所有未结束的事务,一眼就能看出哪个事务已经跑了很久。TRX_AGE_SECONDS超过几百秒的,基本就是嫌疑对象。

拿到trx_mysql_thread_id之后,再去SHOW PROCESSLIST里看这个连接当前在执行什么SQL。很多时候你会发现,根本不是SQL本身慢,而是它在一个事务里做了大量行级修改,整个修改过程产生的redo要同步到只读节点,而只读节点一时半会儿应用不完,延迟自然就上去了。

4.4 慢日志与错误日志怎么读

控制台里的慢日志和错误日志,是两条被很多人忽略的线索。慢日志能帮你找到只读节点上长期存在的高频慢查询。如果一个业务查询在只读节点上经常要跑几十秒,它平时可能不致命,但在流量高峰期就会把节点压垮。错误日志则会记录节点的重启原因、连接被kill的提示、内部异常报错。

看慢日志时不要只看某一条SQL,要看执行次数和总耗时。有些SQL单次只要500毫秒,但1分钟执行几千次,累加起来就是巨大的CPU开销。看错误日志时重点找“Node is not healthy”“Connection closed”“Out of memory”这类关键字,这些往往是节点被摘除或重启的直接证据。

4.5 恢复操作优先级

定位到原因之后,恢复操作按优先级来。如果是连接数打满,先让业务侧缩小连接池规模,或者临时调大max_connections,让节点先恢复响应。如果是CPU被慢查询打满,找到对应SQL并终止它,而不是重启节点,终止单个查询的影响面小得多。如果是规格问题,比如内存长期水位高,才考虑提升只读节点规格。

如果节点已经处于异常状态且无法自行恢复,控制台的重启节点操作可以用,但要有心理预期:冷启动后节点需要重新加载数据缓存,短时间内查询性能会下降。如果节点频繁异常且确认底层有问题,再考虑新建只读节点替换。替换时先创建一个新节点,确认状态正常并追平数据,再删除旧节点,避免出现只有一个从节点且它还在重建中的窘境。

5. 开年“丢人”案例复盘:三次让我印象深刻的从节点故障

理论讲再多,不如复盘几个真实场景。这里讲三个我开年以来遇到过的案例,有我自己踩的坑,也有帮别人擦的尾巴。细节做了脱敏处理,但排查路径是原样的。

5.1 案例一:节后缩容遇上升级窗口,只读节点反复重启

背景是节前业务扩容,加了三个只读节点,节后需要缩到两个。运维同学在控制台里提交了缩容任务,同时因为节前发布了内核小版本升级通知,也顺手勾选了升级。两个任务并到一个变更窗口里,结果缩容任务先执行,其中一个只读节点的规格变更还没完成,升级任务又开始,两边在节点的生命周期状态上打架。

现象就是那个只读节点一直显示“变更中”,然后反复重启,业务侧看到的就是节点时好时坏,监控反复告警。查控制台的变更记录,发现升级任务在等待缩容任务释放资源,而缩容任务又因为升级任务占用资源卡住,形成了一个死锁式的运维状态。

最后是终止了其中一个变更任务,只保留缩容操作,等它彻底完成后,再手动触发一次升级,才恢复正常。复盘之后的结论是:PolarDB的节点生命周期变更必须串行执行,任何两个涉及同一个节点的异步任务都不要同时提交,运维操作前先看变更记录。

5.2 案例二:一个没带WHERE的UPDATE,把只读节点CPU打到100%

这个案例特别“丢人”,因为根因非常简单,一条UPDATE语句忘了加WHERE条件,把一张两千万行的表整表更新了。主节点因为所有写入都在按顺序执行,没有太大感知,但只读节点要应用对应的redo日志,CPU瞬间被打满,紧接着所有从只读节点读取的查询全部排队,业务报表接口超时。

接到告警后我第一反应是看只读节点的进程列表,发现大量查询堆积在同一个节点上,然后查innodb_trx,看到一个事务已经把某张表锁了很久,再追到这条UPDATE,立刻通过连接ID终止了它。终止之后只读节点CPU降下来,复制延迟在几分钟内追平,业务恢复。

后续给这张表加了更新条件和分批更新方案,另外把大事务告警的阈值降到了60秒,任何事务运行超过60秒都会自动通知,避免下次再“裸奔”。

5.3 案例三:新创建的只读节点“永远追不上”

第三个案例和“丢人”关系不大,但很常见。某业务新加了一个只读节点,用于承担一个新的报表分析场景。创建完成后,节点状态显示运行中,但业务反馈查询这个只读节点时数据总是滞后。查复制延迟发现一直维持在几十分钟的水平,而且没有收敛趋势。

刚开始怀疑是不是复制卡住了,但看各个指标都很正常。后面才发现,这个只读节点上有一个长期运行的复杂分析查询,是大范围扫描数据的报表任务,直接把节点的CPU占用了大半,redo日志的应用始终排在后面,延迟自然下不来。

这个案例的解法不是优化复制,而是优化查询。把那个复杂报表改成走独立的数仓分析链路,只读节点专职服务在线业务,延迟马上就降到了秒级以内。新建只读节点就有一个容易被忽略的成本:它刚创建完,数据缓存是空的,不要立刻把大查询压上去,要让节点先“暖”一会儿,我一般会用业务实际读流量预热半小时再开放给报表场景。

6. 常见问题速查表:从现象一步跳到处理方法

把上面这些经验整理成了一张速查表,故障时照着查,能少走不少弯路。

现象可能原因第一步动作根治方案
只读节点连接超时,业务大面积报错节点被健康检查摘除或连接数打满控制台看节点状态和连接数指标调整连接池大小,优化长连接管理
只读节点状态运行中,但查询全部卡住大查询占满CPU,或存在锁等待SHOW PROCESSLIST找到堆积查询终止异常SQL,优化慢查询
复制延迟持续上涨,业务读不到新数据大事务阻塞redo应用,或节点规格不足查innodb_trx找长事务,看复制延迟趋势拆分大事务,提升只读节点规格
节点反复重启,状态在“变更中”打转多个变更任务冲突,或内核升级未完成查变更任务历史记录,确认卡点串行执行运维操作,避免任务并发
只读节点重新创建后,数据一直滞后新节点缓存为空,且有大查询压上来先限制大查询访问,观察延迟趋势预热缓存,逐步放开流量
单个只读节点故障,其他节点正常该节点临时空间不足或参数与集群不一致检查该节点的存储水位和参数值清理临时空间,统一参数模板

这张表里没有特别高深的技术,但每一条都是实打实踩过的坑。把这些内容固化下来,比自己每次从零开始排查效率高得多。

我个人现在处理PolarDB从节点故障的原则很朴素:控制台看三张图,节点上跑三条SQL,再确定恢复动作。遇到从节点不可用,不慌着重启和重建,先花十分钟做一次状态快照。多数从节点不是“坏”了,而是被流量、被查询、被变更压得喘不过气。你给它一点时间,把背后的元凶找出来,它自己就会恢复。至于那些反复出现的故障,把根因写进告警规则和巡检脚本里,下次就不会再在同一个地方丢人了。

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

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

立即咨询