在业务繁忙时,PostgreSQL中的WAL生成量非常大。checkpointer进程会定期清理过期的WAL日志,但在实际生产中,一些不恰当的使用方式可能导致WAL日志未被清理,从而占用大量存储空间。本文介绍主库和只读库发生WAL日志堆积问题时的排查方法。
背景信息
WAL是PostgreSQL中确保数据安全、提高系统可靠性和性能的关键组件。通过WAL机制,PostgreSQL能够在各种故障情况下保证数据不丢失,并且能够可靠地进行恢复。
主库日志堆积
WAL日志堆积问题发生在主库时,可以进行以下排查。
非活跃的复制槽或消费端未及时上报LSN
复制槽(replication slot)是PostgreSQL高可用性和灾难恢复策略的关键工具,其最主要的作用是防止WAL被删除,从而避免复制中断。然而,当复制槽处于非活跃状态时,未被清理的WAL日志会不断累积,导致日志增长过快。
消费端未及时上报LSN时,会导致WAL日志不断增长。
通过系统视图pg_replication_slots可以查看复制槽的各种信息(包括LSN信息)。例如,可以通过以下SQL语句来判断复制槽延迟删除WAL日志的大小。
SELECT slot_name, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_insert_lsn(), restart_lsn)) AS delay_size
FROM pg_replication_slots;如果查询得到的结果较大或与WAL日志堆积量匹配,请根据业务需求评估并删除相应的复制槽。
错误的参数设置
wal_keep_segments、wal_keep_size和max_wal_size参数设置过大都可能会导致实例保留大量WAL日志,请检查这些参数配置并根据业务需求进行调整。
可通过以下 SQL 语句查看 WAL 相关参数的当前值:
select * from pg_settings where name like '%wal%';wal_keep_size:控制pg_wal目录下保留的 WAL 日志最小大小,建议设置不超过 1024 MB。可通过 RDS 控制台的参数设置页面或调用 ModifyParameter 接口修改该参数。max_wal_size:由系统根据实例规格动态计算,计算公式为LEAST(GREATEST(DBInstanceClassMemory/2097152,2048),16384),无需手动设置。
PostgreSQL 13 及以上版本使用 wal_keep_size 取代了 wal_keep_segments,PostgreSQL 9.5 及以上版本使用 max_wal_size 取代了 checkpoint_segments。RDS PostgreSQL 14 及以上版本仅支持新参数。
备份策略异常
WAL 日志在备份完成后由内核在 Checkpoint 操作中自动清理。备份策略异常或备份组件故障会导致 WAL 无法完成备份,日志堆积。
登录 RDS 管理控制台,进入实例详情页,选择备份恢复 > 备份策略。查看日志备份是否开启以及保留天数。日志备份设为不清理时,WAL 将持续保留,属于预期行为。
登录DBS 管理控制台,查看备份计划列表,检查备份任务状态及上传进度。备份任务异常或上传延迟会导致本地 WAL 堆积,可在 DBS 控制台查看备份计划详情,排查任务失败原因。
VACUUM风暴和大量写入
VACUUM风暴通常是指在数据库中同时发生大量的自动或手动VACUUM操作,这些操作可能会产生大量WAL日志,从而导致I/O负载显著增加,影响数据库性能,同时也可能导致WAL无法被及时清理。建议您根据业务需求合理配置VACUUM参数,规划VACUUM操作的执行时间。
大规模写入时出现的情况与VACUUM风暴相似,请根据业务需求合理安排数据写入。
只读库日志堆积
WAL日志堆积问题发生在只读库时,可以进行以下排查。
复制延迟
比较常见的是WAL日志在只读库上的replay延迟,可能的原因有:
只读库上有长时间运行的事务,与WAL日志的replay产生冲突。请根据业务需求评估并调整相关参数(hot_standby_feedback和max_standby_streaming_delay)。
例如,在hot_standby_feedback=off,且max_standby_streaming_delay设置较大时,只读库上运行长事务可能会导致replay延迟。
主库和只读库的规格配置存在差异。如果只读库的计算和存储配置低于主库,可能会导致复制延迟,从而导致未replay的WAL无法清理。请根据业务需求评估并选择合理的只读库配置。
其他原因
对于RDS PostgreSQL实例,如果上述排查后仍未解决WAL堆积的问题,可联系RDS PostgreSQL技术支持进行解决。
相关文档
RDS PostgreSQL实例,您还可以通过手动删除非活跃的Replication Slot来让RDS PostgreSQL内核自动清理WAL日志。具体方法,请参见WAL日志管理。