把 PostgreSQL 日志轮转参数放在一起看:log_rotation_age、log_rotation_size 与 log_truncate_on_rotation

2026-08-29 51 预计阅读时间: 1 分钟
来源: postgr.es AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

PostgreSQL 的日志轮转并不是由一个参数独立决定的。log_rotation_age 控制按时间轮转,log_rotation_size 控制按文件大小轮转,而 log_truncate_on_rotation 决定重新使用同名日志文件时是追加内容还是先截断文件。单独修改其中一个参数,很容易得到与预期不同的日志目录。

三个参数分别管什么

log_rotation_age:文件最多使用多长时间

log_rotation_age 指定单个日志文件最多持续使用的时间。时间到达后,PostgreSQL 会尝试创建新的日志文件。将它设置为 0 可以关闭按时间轮转。

例如:

log_rotation_age = 1d

需要注意,实际文件名还受到 log_filename 的时间格式影响。如果文件名包含小时、日期等 strftime 格式,文件名的变化会参与轮转行为。也就是说,轮转时间和文件名模式应该一起设计,而不是只看 log_rotation_age 的数值。

log_rotation_size:文件不能超过多大

log_rotation_size 指定单个日志文件达到多大后触发轮转。默认值通常是 10MB,也可以设置为 0 禁用按大小轮转。

log_rotation_size = 100MB

时间条件和大小条件是“谁先到谁触发”。例如设置为每天轮转、每个文件最多 100MB,那么高峰期可能几分钟就生成一个新文件;低流量时则可能接近一天才轮转一次。

log_truncate_on_rotation:重名文件是追加还是覆盖

这个参数只在轮转后重新使用一个已经存在的文件名时特别重要:

  • off:默认行为,更倾向于向已有文件追加内容;
  • on:创建文件时先截断已有内容,再从空文件开始写入。

它通常要和带有时间字段的 log_filename 一起理解。例如:

log_filename = 'postgresql-%Y-%m-%d_%H%M.log'
log_truncate_on_rotation = on

如果文件名包含足够细的时间信息,文件名重复的机会较低,截断行为也不常被触发。如果使用只包含星期几或小时的循环文件名,旧文件会被周期性重用,此时 on 可能导致旧日志被覆盖。生产环境中不要把它误当成日志归档策略。

推荐的配置组合

一个偏向日常运维的配置可以这样写:

logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M.log'
log_rotation_age = 1d
log_rotation_size = 100MB
log_truncate_on_rotation = off

这组配置表达了几个清晰的决策:

  1. 日志文件通常按天轮转;
  2. 如果一天内日志量很大,达到 100MB 就提前轮转;
  3. 文件名带有日期和分钟,便于定位时间段;
  4. 不主动截断旧文件,避免因为文件名模式重复而静默丢失历史内容。

如果你明确需要循环复用固定数量的文件,例如只保留一组按星期命名的文件,可以考虑:

log_filename = 'postgresql-%a.log'
log_rotation_age = 1d
log_rotation_size = 0
log_truncate_on_rotation = on

这不是归档配置,而是“有限数量文件循环使用”的配置。它会牺牲历史日志保留能力,必须配合外部采集、压缩或远程存储系统使用。

可以直接执行的检查与修改

先查看当前值:

psql -d postgres -c "SHOW log_rotation_age;"
psql -d postgres -c "SHOW log_rotation_size;"
psql -d postgres -c "SHOW log_truncate_on_rotation;"
psql -d postgres -c "SHOW log_filename;"

确认影响范围后,可以使用 ALTER SYSTEM 写入 PostgreSQL 的自动配置文件:

psql -d postgres <<'SQL'
ALTER SYSTEM SET log_rotation_age = '1d';
ALTER SYSTEM SET log_rotation_size = '100MB';
ALTER SYSTEM SET log_truncate_on_rotation = 'off';
ALTER SYSTEM SET log_filename = 'postgresql-%Y-%m-%d_%H%M.log';
SELECT pg_reload_conf();
SQL

随后再次检查:

psql -d postgres -c "SELECT name, setting, unit, context FROM pg_settings WHERE name IN ('log_rotation_age', 'log_rotation_size', 'log_truncate_on_rotation', 'log_filename');"

这些参数通常可以通过配置重载生效,但已经打开的日志文件不会因为一次重载就被任意拆分。验证时,应观察新文件是否按预期创建,而不是只检查配置文件中的文本。

设计日志轮转时别忘了这几个边界

文件大小不是磁盘配额

log_rotation_size 约束的是单个日志文件,不是整个日志目录。高并发实例可能在短时间内生成很多文件,因此仍然需要设置日志保留周期、压缩策略和磁盘告警。

轮转不是清理

PostgreSQL 负责创建新文件,但不会自动替你完成完整的历史日志生命周期管理。可以由 logrotate、systemd journal、云日志代理或集中式日志系统负责压缩、上传和删除。

log_truncate_on_rotation 有数据丢失风险

只要文件名会重复,on 就意味着旧内容可能被覆盖。除非这是经过确认的循环日志设计,否则生产环境通常更适合使用唯一性更高的文件名,并保持 off

轮转条件要按峰值流量估算

如果业务高峰每小时产生 2GB 日志,把 log_rotation_size 设置为 1GB 仍然会得到大量文件。应结合采集器的上传能力、单文件处理限制和故障排查习惯选择大小,而不是机械套用默认值。

一份落地检查清单

  • 确定需要按时间、按大小,还是两者取先到;
  • 检查 log_filename 是否会周期性复用同名文件;
  • 非循环覆盖场景优先使用 log_truncate_on_rotation = off
  • 把单文件大小与日志目录总容量分开规划;
  • 用实际峰值日志量验证轮转频率;
  • 为旧日志配置压缩、归档和删除策略;
  • 修改后通过 SHOW 和日志目录变化共同验证。

把这三个 GUC 放在同一张设计表里,日志轮转就不再是“改一个参数试试看”,而会变成一组可解释、可验证、可回滚的运维策略。


相关推荐