WAL日志堆积问题定位及处理方法
指标异常说明
PostgreSQL使用WAL(Write-Ahead Logging)日志机制来保证数据的持久性和一致性。WAL 日志记录了对数据库的所有更改操作,在主备复制、崩溃恢复、逻辑复制等场景中都扮演关键角色。
数据库提供了以下与WAL日志相关的监控指标,建议重点关注以下指标:
- 事务日志使用量(WAL日志):rds040_transaction_logs_usage
- 非活跃逻辑复制槽数量:inactive_logical_replication_slot
- 最滞后副本滞后量(因复制槽积压的WAL日志):rds045_oldest_replication_slot_lag
- 事务日志生成速率:rds044_transaction_logs_generations
排查及解决方法
- 查看WAL日志大小是否异常并进行处理
首先通过查看监控rds040_transaction_logs_usage,观察WAL日志占用容量大小。观察WAL日志大小近期是否有明显上涨,或WAL日志占比磁盘容量较大。
也可以通过下述SQL,查看WAL日志大小。如果发现WAL非常多,可以通过后续步骤依次排查。
select pg_size_pretty(sum(size)) from pg_ls_waldir();
- 查看复制槽状态及延迟未清理的日志大小
复制槽会阻塞WAL的回收,查看监控指标inactive_logical_replication_slot如果不为0,且rds045_oldest_replication_slot_lag的堆积的WAL日志数据较大,甚至与rds040_transaction_logs_usage基本一致,表示复制槽阻塞WAL日志回收。
或者通过下述SQL查询slot状态及WAL日志滞后量:
select slot_name, active, pg_size_pretty(pg_wal_lsn_diff(b, a.restart_lsn)) as slot_latency from pg_replication_slots as a, pg_current_wal_lsn() as b;
如果查询结果中,active字段存在'f' 状态的slot,并且slot_latency字段的大小很大,表示非活跃复制槽阻塞了WAL日志回收,导致WAL日志堆积无法清理。
需要分析该复制槽是否还需要,如果不需要,建议执行删除slot命令的SQL:
select pg_drop_replication_slot('slot_name');
- 查看WAL日志保留相关参数
查看数据库参数“wal_keep_segments”、“wal_keep_size”、“max_wal_size”的值是否设置过大。
select name, setting from pg_settings where name in ('wal_keep_segments', 'wal_keep_size', 'max_wal_size');
- 对于RDS for PostgreSQL 12及以下版本,查看“wal_keep_segments”参数的值;对于12以上版本,查看“wal_keep_size”参数的值。
- WAL日志保留参数的值不宜太大,一般设置要小于磁盘总空间的10%;也不宜太小,一般要大于4GB,否则容易导致主库将备库需要的wal日志清理,进而导致备库异常。
- 查看写业务繁忙程度
可以通过rds044_transaction_logs_generations指标查看写业务繁忙程度,该指标表示平均每秒生成的事务日志(WAL日志)大小。
如果该指标较大(平均超过50MB/s),说明写业务较多,数据库内核会自动预留更多的WAL日志以便回收使用,WAL日志占用的磁盘空间会增加,建议通过磁盘扩容保证一定的磁盘冗余。
备份期间的WAL日志
如果WAL上升时,数据库处于备份状态,在备份完成后,WAL日志大小恢复正常,则表示备份期间WAL日志生成较快,导致备份速度赶不上生成速度。
可以调整备份时间,避免备份期间存在大量数据写入,或者扩大磁盘留足缓存容量。