一、为什么需要日志轮转

数据库运行过程中会产生大量日志文件,如果不加以管理,这些文件很快就会占满磁盘空间。想象一下,你正在度假,突然收到服务器磁盘告警,不得不紧急处理——这种场景谁都不想遇到。PostgreSQL 默认会将日志输出到单个文件中,随着时间推移,这个文件可能增长到几个 GB 甚至更大,不仅占用空间,还会影响日志查阅效率。

日志轮转(Log Rotation)就是解决这个问题的标准方案。它通过定期归档、压缩旧日志,并创建新日志文件,确保日志总量可控。在 Linux 系统中,logrotate 是完成这项任务的经典工具,它支持按时间、按大小触发轮转,还能在轮转后执行自定义命令(比如通知 PostgreSQL 重新打开日志文件)。

二、logrotate 基础配置

我们先来看一个最简单的 logrotate 配置示例(技术栈:Linux + PostgreSQL):

# /etc/logrotate.d/postgresql  
/var/log/postgresql/postgresql.log {  
    daily                      # 每天轮转一次  
    missingok                  # 如果日志文件不存在也不报错  
    rotate 7                   # 保留最近7天的日志  
    compress                   # 压缩旧日志  
    delaycompress              # 下一次轮转时再压缩  
    notifempty                 # 如果日志为空则不轮转  
    sharedscripts              # 所有日志处理完再执行脚本  
    postrotate                 # 轮转后执行的命令  
        /usr/bin/pg_ctl reload -D /var/lib/postgresql/data >/dev/null  
    endscript  
}  

关键参数解析

  • daily/weekly/monthly:轮转周期,也可用 size(例如 size 100M
  • rotate N:保留的历史日志数量
  • compress:用 gzip 压缩旧日志(生成 .gz 文件)
  • postrotate:这里通过 pg_ctl reload 让 PostgreSQL 重新打开日志文件

三、分离错误日志与查询日志

实际生产中,我们通常希望将错误日志(error log)和查询日志(query log)分开管理。PostgreSQL 通过 logging_collectorlog_destination 参数控制日志行为。修改 postgresql.conf

# 启用日志收集器  
logging_collector = on  
# 日志输出到文件  
log_destination = 'stderr'  
# 错误日志路径  
log_directory = '/var/log/postgresql'  
log_filename = 'postgresql-error.log'  
# 开启查询日志(慎用,对性能有影响)  
log_statement = 'all'  
# 查询日志单独存放  
log_line_prefix = '%t [%p] '  # 时间戳和进程ID  

对应的 logrotate 配置需调整为:

# /etc/logrotate.d/postgresql  
/var/log/postgresql/postgresql-error.log {  
    daily  
    rotate 30                  # 错误日志保留更久  
    compress  
    postrotate  
        /usr/bin/pg_ctl reload -D /var/lib/postgresql/data  
    endscript  
}  

/var/log/postgresql/postgresql-query.log {  
    weekly                     # 查询日志轮转频率较低  
    rotate 4                   # 保留4周  
    size 100M                  # 或达到100MB时轮转  
    compress  
    delaycompress  
    postrotate  
        /usr/bin/pg_ctl reload -D /var/lib/postgresql/data  
    endscript  
}  

四、高级技巧与注意事项

1. 手动触发轮转测试

不要等到自动轮转时才发现配置错误,可以手动运行以下命令测试:

logrotate -vf /etc/logrotate.d/postgresql  

-v 显示详细过程,-f 强制立即执行。

2. 处理权限问题

如果 PostgreSQL 以非 root 用户运行,需确保日志目录权限正确:

chown postgres:postgres /var/log/postgresql  
chmod 750 /var/log/postgresql  

3. 避免日志丢失

postrotate 脚本中,pg_ctl reload 是关键。如果忘记这一步,PostgreSQL 会继续向已轮转的旧文件写入日志,导致新日志文件为空。

4. 性能权衡

全量查询日志(log_statement = 'all')会显著增加 I/O 负载,建议仅在调试时开启,生产环境可改为 'ddl''mod'

五、应用场景与总结

典型场景

  • 合规性要求保留一定期限的数据库日志
  • 磁盘空间有限的中小型数据库实例
  • 需要定期分析错误日志的运维监控系统

优点

  • 自动化管理,避免手动清理
  • 压缩旧日志节省空间
  • 与 Linux 生态无缝集成

缺点

  • 需要正确配置 postrotate 脚本
  • 频繁轮转可能增加 CPU 负载(压缩操作)

最终建议
对于高负载生产环境,可考虑将日志发送到 ELK 或 Prometheus 等集中式日志系统,但 logrotate 仍是轻量级方案的优选。配置完成后,建议通过 cron 日志检查轮转是否正常执行,例如:

grep logrotate /var/log/cron.log