返回首页

磁盘 94% 告警,数据库才 57MB——1800 倍的差额到底藏在哪?

磁盘 94% 告警,数据库才 57MB——1800 倍的差额到底藏在哪?

大家好,我是老张。

上午10 点,手机震了——「PG 实例磁盘使用率超过 90%,当前值 94.84%」。

迷迷糊糊爬起来,打开控制台一看:实例规格 100GB 磁盘,已经吃掉了 94.84GB。第一反应——是不是业务库数据暴增了?

结果进库一看:

  datname   |  size
------------+---------
 业务库     | 57 MB
 postgres   | 8873 kB
 template1  | 8385 kB

57MB。 整个业务库的数据加起来才 57MB,磁盘却占了 94GB。差了 1800 倍。

这不是数据的问题。剩下的 94GB 到底是什么?


📊 告警来了 → 第一层:控制台确认

告警原文(已脱敏):

[Database][RDS_PG] 实例磁盘使用率超过 90%
实例:某 PG 14 实例(4C8G,100GB 本地 SSD)
当前值:94.84%

登录控制台 → 实例详情 → 「服务可用性」页面:

指标数值
磁盘总量100 GB
磁盘使用率94.84%
数据57 MB
WAL 日志94.2 GB ← 这里

一眼定位——不是数据膨胀,是 WAL 日志占了 94GB

关键判断:控制台「服务可用性」页面分拆了数据 / WAL / 其他日志的占比,省去了进 Pod 盲猜的环节。收到磁盘告警第一步先看这个分拆,不要上来就怀疑数据疯涨。


🔬 第二层:进 Pod,确认 WAL 堆积

进主节点 Pod 看文件系统:

$ du -sh /pgdata/
88G     /pgdata/
$ du -ah /pgdata/ | sort -rh | head -5
88G     /pgdata/xxx/pg_wal        ← 88GB
88G     /pgdata/xxx
83M     /pgdata/xxx/base
58M     /pgdata/xxx/base/16501

pg_wal 目录独占 88GB。数一下文件:

$ ls /pgdata/xxx/pg_wal/ | wc -l
2811

2811 个 WAL 文件。 正常的 PG 实例,WAL 文件数通常在两位数(几十到一百),2800+ 明显不正常。


🎯 第三层:根因定位——废弃复制槽

PG 的 WAL 为什么不被清理?最常见的原因是 复制槽(Replication Slot)——主库给备库留的"书签"。

SELECT slot_name, active,
       pg_size_pretty(
         pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)
       ) AS wal_retained
FROM pg_replication_slots;

结果:

              slot_name               | active | wal_retained
--------------------------------------+--------+--------------
 postgres_xxxx_fdfdf795f_psg8v        | f      | 88 GB

就一个槽,INACTIVE,堆积了 88GB。

PG 的机制:只要复制槽存在——不管 ACTIVE 还是 INACTIVE——restart_lsn 之前的 WAL 就全部保留,不会被 checkpoint 回收。

这个槽是谁创建的?槽名里的 psg8v 是备节点 Pod 的随机后缀。备节点在 179 天前重建过,Pod 名变了,新 Pod 用了新的复制槽,但旧槽没有被自动删除,成了孤儿。


🛡️ 删槽前的安全性验证

删槽不可逆,删错了备库同步会断。先做三步验证:

检查项命令结果结论
备节点是否有槽进备节点查 pg_replication_slots0 rows备节点不用这个槽
主节点活跃复制pg_stat_replication0 rows无任何复制连接
废弃槽 lagpg_wal_lsn_diff(...)87.7 GB纯堆积,无人使用

三项交叉验证通过 → 安全删除


🔧 处理

SELECT pg_drop_replication_slot('postgres_xxxx_fdfdf795f_psg8v');

一条 SQL,删了槽。

但 WAL 不会立刻回收——PG 的 checkpoint 是异步的,加上归档(pgbackrest)需要追完积压队列。本例堆积了 2800+ 个 WAL 文件,等了约 10 分钟


📈 处理效果

指标处理前处理后
磁盘使用率94.84%2.79%
WAL 目录大小88 GB2.1 GB
WAL 文件数281167

94.84% → 2.79%,告警消除 ✅


🧠 老张的几点总结

1. 磁盘告警,先看控制台分拆

不要上来就 du -sh。控制台的「服务可用性」页面已经把数据/Binlog/WAL/其他日志的比例列出来了。一眼就能判断是数据膨胀还是日志堆积,省掉大半排查时间。

2. 数据 57MB、磁盘 94GB → 99% 是 WAL 堆积

这种"数据小、磁盘满"的极端反差,基本锁定 WAL 堆积。下一步直接查复制槽。

3. 复制槽排查三步

-- ① 看有没有堆积
SELECT slot_name, active,
       pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn))
FROM pg_replication_slots;

-- ② 看有没有人在用
SELECT * FROM pg_stat_replication;

-- ③ 交叉验证:备节点查自己的槽
-- (进备 Pod 执行)
SELECT * FROM pg_replication_slots;

三步走完,INACTIVE + 无复制连接 + 备节点不用此槽 → 安全删除。

4. 废弃槽不会自动清理

PG 管控侧不会自动检测和清理 INACTIVE 的复制槽。备节点重建、重配、或主备切换场景下,旧槽容易变成孤儿。建议纳入日常巡检:pg_replication_slotsactive = falsewal_retained > 10GB 的槽需要人工确认后清理。


📋 排查清单(建议收藏)

  • 控制台 → 实例详情 → 服务可用性 → 看数据/WAL/日志分拆
  • 如果 WAL 占比高 → 进 Pod,du -sh /pgdata/*/pg_wal/
  • ls pg_wal/ | wc -l 确认文件数(正常 < 200)
  • SELECT * FROM pg_replication_slots 查槽状态
  • SELECT * FROM pg_stat_replication 确认活跃连接
  • 备节点 pg_replication_slots 交叉验证
  • 三项验证通过 → pg_drop_replication_slot('槽名')
  • 等 5-10 分钟,控制台确认磁盘恢复

💬 互动话题

  1. 你遇到过 PG WAL 堆积的问题吗?最终是什么原因导致的?
  2. 你们公司的 PG 巡检有没有覆盖复制槽状态?多久查一次?
  3. 除了复制槽,还有哪些情况会导致 WAL 不回收?评论区聊聊
A

Admin

用文字记录生活与思考。

评论 (0)
暂无评论,来抢沙发吧
磁盘 94% 告警,数据库才 57MB——1800 倍的差额到底藏在哪? | 山外云的Vlog