Skip to content

日志轮换与归档

日志轮换与归档是PostgreSQL运维中的重要组成部分,它确保了日志文件的合理管理,避免日志文件过大占用过多磁盘空间,同时保证了日志的安全性和可访问性。本文将详细介绍PostgreSQL日志轮换与归档的配置、管理方法和最佳实践。

内置日志轮换

PostgreSQL内置了日志轮换功能,可以根据时间或大小自动轮换日志文件。

1. 基本配置

ini
# 日志文件目录
log_directory = '/var/log/postgresql'  # 绝对路径,建议将日志存储在独立分区

# 日志文件名称格式
log_filename = 'postgresql-%Y-%m-%d.log'  # 按天生成日志文件

# 日志轮换策略
log_rotation_age = 1d  # 每天轮换一次
log_rotation_size = 100MB  # 当文件大小超过100MB时轮换

# 同一时间段的日志文件是否覆盖
log_truncate_on_rotation = off  # 关闭覆盖,保留多个日志文件

# 日志文件权限
log_file_mode = 0640  # 日志文件权限,确保只有授权用户可以访问

2. 轮换策略选项

基于时间的轮换

ini
# 每天轮换一次
log_rotation_age = 1d

# 每小时轮换一次
# log_rotation_age = 1h

# 每分钟轮换一次(仅用于调试)
# log_rotation_age = 1min

基于大小的轮换

ini
# 当文件大小超过100MB时轮换
log_rotation_size = 100MB

# 当文件大小超过1GB时轮换
# log_rotation_size = 1GB

# 禁用基于大小的轮换
# log_rotation_size = 0

混合轮换策略

PostgreSQL支持同时配置基于时间和基于大小的轮换策略,满足任意一个条件就会触发轮换:

ini
# 每天轮换一次,或当文件大小超过100MB时轮换
log_rotation_age = 1d
log_rotation_size = 100MB

3. 日志文件命名格式

PostgreSQL支持多种日志文件命名格式,包括时间戳、星期几、月份等:

ini
# 按年月日命名(推荐)
log_filename = 'postgresql-%Y-%m-%d.log'  # 生成类似 postgresql-2023-10-15.log

# 按年月日时分秒命名(适合高频轮换)
# log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'  # 生成类似 postgresql-2023-10-15_143025.log

# 按星期几命名
# log_filename = 'postgresql-%a.log'  # 生成类似 postgresql-Mon.log, postgresql-Tue.log

# 按月份命名
# log_filename = 'postgresql-%b.log'  # 生成类似 postgresql-Oct.log

使用logrotate管理日志

对于更复杂的日志管理需求,可以使用Linux系统的logrotate工具来管理PostgreSQL日志。

1. logrotate配置

创建logrotate配置文件:

bash
# 创建logrotate配置文件
cat > /etc/logrotate.d/postgresql << EOF
/var/log/postgresql/postgresql-*.log {
    daily                    # 每天轮换一次
    rotate 7                  # 保留7天的日志
    compress                 # 压缩旧日志
    delaycompress            # 延迟压缩,保留最新的一个日志不压缩
    missingok                # 忽略不存在的文件
    notifempty               # 不压缩空文件
    create 0640 postgres postgres  # 创建新文件的权限和所有者
    su postgres postgres     # 以postgres用户身份运行
    sharedscripts            # 所有文件轮换后只执行一次脚本
    postrotate               # 轮换后执行的脚本
        # 向PostgreSQL发送SIGHUP信号,重新打开日志文件
        /bin/kill -HUP $(cat /var/run/postgresql/14-main.pid 2>/dev/null) 2>/dev/null || true
    endscript
}
EOF

2. logrotate常用选项

选项描述
daily每天轮换一次
weekly每周轮换一次
monthly每月轮换一次
rotate N保留N个日志文件
compress压缩旧日志文件
delaycompress延迟压缩,保留最新的一个日志文件不压缩
missingok忽略不存在的文件
notifempty不压缩空文件
create MODE OWNER GROUP创建新文件的权限、所有者和组
su USER GROUP以指定用户身份运行
sharedscripts所有文件轮换后只执行一次脚本
postrotate/endscript轮换后执行的脚本
prerotate/endscript轮换前执行的脚本

3. 手动运行logrotate

bash
# 测试logrotate配置
logrotate -d /etc/logrotate.d/postgresql

# 手动运行logrotate
logrotate /etc/logrotate.d/postgresql

# 强制运行logrotate,即使未到轮换时间
logrotate -f /etc/logrotate.d/postgresql

# 查看logrotate状态
logrotate -s /var/lib/logrotate/status /etc/logrotate.d/postgresql

日志归档策略

1. 本地归档

将日志归档到本地磁盘,适合小规模部署:

bash
# 创建归档目录
mkdir -p /archive/postgresql/logs

# 配置cron定期归档
0 0 * * * find /var/log/postgresql -name "postgresql-*.log.gz" -mtime +7 -exec mv {} /archive/postgresql/logs/ \;

# 清理旧归档
0 0 1 * * find /archive/postgresql/logs -name "postgresql-*.log.gz" -mtime +365 -delete

2. 远程归档

将日志归档到远程服务器,提高日志的安全性:

bash
# 使用rsync归档到远程服务器
0 0 * * * rsync -avz --remove-source-files /var/log/postgresql/postgresql-*.log.gz backup@remote-server:/archive/postgresql/logs/

# 使用scp归档到远程服务器
0 0 * * * scp /var/log/postgresql/postgresql-*.log.gz backup@remote-server:/archive/postgresql/logs/ && rm /var/log/postgresql/postgresql-*.log.gz

3. 云存储归档

将日志归档到云存储服务,如AWS S3、阿里云OSS等:

bash
# 安装AWS CLI
pip install awscli

# 配置AWS凭证
aws configure

# 配置cron定期归档到S3
0 0 * * * aws s3 sync /var/log/postgresql s3://my-postgresql-logs/ --exclude "*.log" --include "*.log.gz"

# 清理本地旧日志
0 1 * * * find /var/log/postgresql -name "postgresql-*.log.gz" -mtime +7 -delete

日志保留策略

1. 基于时间的保留

根据合规要求和存储空间,设置合理的日志保留时间:

日志类型保留时间建议
错误日志30-90天保留足够长的时间,便于故障排查
慢查询日志7-30天根据查询量和存储空间调整
审计日志1-7年根据合规要求调整,如PCI DSS要求保留1年
WAL日志7-30天至少保留到下一次完整备份

2. 基于大小的保留

除了基于时间的保留外,还可以根据日志文件大小设置保留策略:

bash
# 保留不超过10GB的日志文件
0 0 * * * while [ $(du -s /var/log/postgresql | awk '{print $1}') -gt 10485760 ]; do rm -f $(ls -t /var/log/postgresql/postgresql-*.log.gz | tail -1); done

日志压缩

1. 内置压缩

PostgreSQL 14+支持内置的日志压缩功能:

ini
# 启用日志压缩
log_compression = on  # 可选值:on, off

# 压缩算法(PostgreSQL 14+)
# log_compression_algorithm = gzip  # 可选值:gzip, lz4, zstd

2. 外部压缩

对于旧版本的PostgreSQL,可以使用外部工具压缩日志:

bash
# 使用gzip压缩日志
find /var/log/postgresql -name "postgresql-*.log" -mtime +1 -exec gzip {} \;

# 使用lz4压缩日志(更快的压缩速度)
find /var/log/postgresql -name "postgresql-*.log" -mtime +1 -exec lz4 -z {} \;

# 使用zstd压缩日志(更好的压缩率)
find /var/log/postgresql -name "postgresql-*.log" -mtime +1 -exec zstd -z {} \;

日志管理最佳实践

1. 生产环境配置建议

ini
# 日志输出配置
log_destination = 'stderr'
logging_collector = on
log_directory = '/var/log/postgresql'
log_filename = 'postgresql-%Y-%m-%d.log'
log_rotation_age = 1d
log_rotation_size = 100MB
log_truncate_on_rotation = off
log_file_mode = 0640

# 日志格式配置
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
log_process_id = on
log_session_identifier = on

# 日志内容配置
log_min_messages = warning
client_min_messages = notice
log_error_verbosity = default
log_context_lines = 10

2. 存储建议

  • 使用独立分区:将日志存储在独立分区,避免日志过大影响数据库性能
  • 使用SSD存储:日志写入是顺序I/O,SSD可以提供更好的性能
  • 监控磁盘空间:设置磁盘空间告警,避免日志占满磁盘
  • 定期备份日志:将日志备份到异地,提高安全性

3. 安全性建议

  • 限制日志访问权限:确保只有授权用户可以访问日志文件
  • 加密敏感信息:避免在日志中记录敏感信息,如密码
  • 定期审查日志:定期审查日志,识别异常行为
  • 使用安全的日志传输:远程归档时使用加密传输(如rsync over SSH)

4. 性能优化

  • 合理设置轮换策略:避免过于频繁的轮换,减少I/O开销
  • 使用合适的压缩算法:根据需求选择压缩速度和压缩率平衡的算法
  • 异步日志写入:对于非关键业务,可以使用异步日志写入
  • 避免日志级别过高:只记录必要的日志级别,减少日志量

常见问题与解决方案

1. 日志文件过大

问题:日志文件增长过快,占用过多磁盘空间

解决方案

  • 调整log_rotation_age和log_rotation_size参数,增加轮换频率
  • 减少日志级别,只记录必要的信息
  • 关闭不必要的日志记录,如log_statement=none
  • 启用日志压缩
  • 使用logrotate工具管理日志

2. 日志轮换失败

问题:内置日志轮换功能失败,日志文件没有按预期轮换

解决方案

  • 检查log_directory目录权限是否正确
  • 确保PostgreSQL进程有写权限
  • 检查postgresql.conf中的日志配置是否正确
  • 查看PostgreSQL错误日志,获取详细错误信息
  • 考虑使用logrotate工具替代内置轮换

3. 日志归档失败

问题:日志归档到远程服务器失败

解决方案

  • 检查网络连接是否正常
  • 验证远程服务器的访问权限
  • 检查归档脚本是否有错误
  • 查看系统日志,获取详细错误信息
  • 考虑使用更可靠的归档工具,如rsync with --timeout选项

4. 日志丢失

问题:日志文件丢失,无法查看历史日志

解决方案

  • 检查日志轮换和归档策略是否正确
  • 确保日志文件权限设置正确,避免被意外删除
  • 配置日志备份,定期将日志复制到安全位置
  • 使用版本控制系统管理配置文件,避免误配置

版本差异注意事项

PostgreSQL版本差异

版本日志轮换特性差异
PostgreSQL 16增强了日志压缩功能,支持更多压缩算法
PostgreSQL 14引入了内置日志压缩功能
PostgreSQL 13改进了日志收集器,支持更灵活的日志配置
PostgreSQL 10支持多目标日志输出
PostgreSQL 9.x基本的内置日志轮换功能

logrotate版本差异

版本主要变化
logrotate 3.18+支持zstd压缩算法
logrotate 3.17+支持lz4压缩算法
logrotate 3.15+改进了错误处理
logrotate 3.14+支持--dry-run选项

总结

日志轮换与归档是PostgreSQL运维中的重要组成部分,它确保了日志文件的合理管理,避免日志文件过大占用过多磁盘空间,同时保证了日志的安全性和可访问性。通过合理配置内置日志轮换功能或使用logrotate工具,可以有效地管理PostgreSQL日志。

在实际运维中,DBA应该:

  1. 根据实际需求选择合适的日志轮换策略
  2. 配置合理的日志保留时间,满足合规要求
  3. 选择合适的归档方式,提高日志的安全性
  4. 定期审查日志,识别异常行为
  5. 监控日志磁盘空间,避免日志占满磁盘

通过有效的日志轮换与归档管理,可以提高PostgreSQL的可靠性和安全性,便于故障排查和性能优化。