PostgreSQL 的日志参数很多,真正困难的地方不是记住每个 GUC 的名字,而是把日志和服务器正在做的事情对应起来:检查点是否造成 I/O 峰值,autovacuum 是否跟不上表的变化速度,临时文件是否暴露了内存或查询计划问题。
从 PostgreSQL 8.3 开始,服务器的自动维护更加积极:autovacuum 默认启用,检查点也不再简单地把工作集中在时间窗口末尾。要理解这些后台行为,日志是比猜测更可靠的入口。
三个 GUC 分别回答什么问题
log_checkpoints:检查点是否制造了 I/O 压力
启用 log_checkpoints 后,每次检查点完成时,PostgreSQL 会记录检查点持续时间、写入的数据量,以及同步阶段的耗时等信息。它适合回答:
- 检查点是否过于频繁?
- 单次检查点是否写入了大量脏页?
- 写入或同步阶段是否占用了明显时间?
检查点日志不等于完整的 I/O 诊断,但它能把“磁盘偶尔很忙”的现象和具体服务器事件联系起来。若日志显示检查点频率高、持续时间长,通常还需要结合 checkpoint_timeout、checkpoint_completion_target、max_wal_size 以及存储系统指标一起判断。
log_autovacuum_min_duration:autovacuum 做了什么,以及花了多久
这个参数控制 autovacuum 日志的最短持续时间。设置为 0 会记录所有自动清理和自动分析操作;设置为正数则只记录持续时间达到该毫秒数的操作;设置为 -1 会关闭这类日志。
例如,log_autovacuum_min_duration = 5s 可以过滤掉很快完成的任务,优先留下值得调查的表。日志中通常可以看到表名、删除或回收的元组数量,以及是否需要进一步处理。
它特别适合发现以下情况:
- 某些高写入表经常触发较慢的 vacuum;
- 清理工作需要扫描大量数据;
- 表的统计信息更新耗时,导致优化器长期使用过时信息;
- autovacuum worker 可能被持续的写入压力拖住。
日志只能告诉你发生了什么,不能自动证明某个 autovacuum 参数应该增大或减小。调优时还要观察表膨胀、事务年龄、dead tuples 和业务写入模式。
log_temp_files:查询何时溢出到临时文件
排序、哈希、物化等操作在内存不足时可能创建临时文件。log_temp_files 使用 KB 作为单位:设置为 0 记录所有临时文件,设置为正数则只记录大小达到该阈值的文件,设置为 -1 关闭记录。
临时文件本身不是错误。适量的临时文件可能是正常的查询执行结果;但如果某类查询频繁产生很大的临时文件,就值得检查:
work_mem是否过小;- 查询是否发生了不必要的大排序或哈希;
- 统计信息是否过时,导致计划选择不佳;
- 单个连接可能同时运行多个操作,盲目增大
work_mem是否会耗尽内存。
这里有一个重要边界:work_mem 是每个操作、每个查询节点的预算,不是每个连接的总预算。因此不能因为看到临时文件,就在全局范围内直接把它调到很大。
一套可复制的观测配置
可以先在一个有限时间窗口内启用较详细的日志,再根据结果收紧阈值。下面的配置适合排查检查点、autovacuum 和临时文件问题;具体数值需要结合实例负载调整。
-- 需要足够权限;部分参数会要求 reload 或重启。
ALTER SYSTEM SET log_checkpoints = on;
ALTER SYSTEM SET log_autovacuum_min_duration = '5s';
ALTER SYSTEM SET log_temp_files = '1MB';
-- 让日志带上时间、进程和会话信息,便于关联查询。
ALTER SYSTEM SET log_line_prefix = '%m [%p] db=%d,user=%u,app=%a ';
SELECT pg_reload_conf();
-- 确认当前生效值。
SELECT name, setting, unit, source
FROM pg_settings
WHERE name IN (
'log_checkpoints',
'log_autovacuum_min_duration',
'log_temp_files',
'log_line_prefix'
)
ORDER BY name;
运行前应确认 ALTER SYSTEM 写入的配置文件由 PostgreSQL 进程用户管理,并确认日志收集已经启用。实际部署中还要检查日志轮转、保留周期和磁盘空间,避免排查问题时反过来制造日志磁盘告警。
如果你想捕获完整的 autovacuum 活动,可以临时使用:
ALTER SYSTEM SET log_autovacuum_min_duration = 0;
SELECT pg_reload_conf();
观察一个足够代表业务流量的时间段后,再恢复为更高的阈值,例如 5s 或 10s。持续永久记录所有操作可能产生大量日志,尤其是在表很多、写入频繁的实例上。
怎样读这些日志,而不是只收集它们
建议把日志分析分成三个维度。
第一,看频率。检查点是否集中出现,临时文件是否由同一个应用反复创建,某张表的 autovacuum 是否比其他表更频繁。
第二,看单次成本。一次检查点写入多少数据,autovacuum 扫描或清理了多少元组,临时文件有多大。单条慢日志通常不如一段时间内的分布有价值。
第三,和其他指标关联。检查点日志应与 WAL 生成量、磁盘延迟和吞吐量一起看;autovacuum 日志应与 dead tuples、表大小和事务年龄一起看;临时文件日志应与查询文本、执行计划和内存使用一起看。
可以用一个简单的 shell 命令先筛选日志中的关键词:
# 将日志文件路径替换为你的实际日志目录。
rg -n 'checkpoint|automatic vacuum|automatic analyze|temporary file' /var/log/postgresql/
更可靠的做法是使用结构化日志或日志采集系统,将时间、数据库、用户、应用名和进程 ID 作为字段保存。这样可以按应用和时间窗口聚合,而不是依赖人工翻阅长文本。
常见误区与落地建议
不要把“有临时文件”直接等同于“必须增大 work_mem”。先确认查询计划和并发量,再决定是改写查询、更新统计信息、调整索引,还是只对特定会话提高 work_mem。
不要把 autovacuum 日志阈值设成永久的 0,除非日志量经过评估并且确实有长期审计需求。排查阶段需要更高可见性,常态运行则需要控制噪声。
不要孤立解读检查点耗时。检查点变慢可能是脏页积累、存储延迟、WAL 配置或系统资源竞争共同造成的。
一个实用的工作循环是:
- 先启用三个日志 GUC,并设置有限的时间窗口。
- 按频率、持续时间和对象名称聚合日志。
- 用数据库和操作系统指标验证假设。
- 只调整一个相关参数,观察变化。
- 解决问题后收紧日志阈值,并保留一份排查结论。
这些 GUC 的价值不在于让日志变得更多,而在于让后台维护和查询执行的代价变得可见。日志能告诉你 PostgreSQL 在忙什么;接下来如何调参,仍然要由负载、存储和并发模型共同决定。