外观
PostgreSQL 日志配置
PostgreSQL日志是数据库运维中重要的信息来源,它记录了数据库的运行状态、错误信息、慢查询等关键数据。合理配置PostgreSQL日志可以帮助DBA及时发现问题、分析性能瓶颈和进行故障排查。本文将详细介绍PostgreSQL日志的配置方法和最佳实践。
日志配置参数
PostgreSQL提供了丰富的日志配置参数,可以通过修改postgresql.conf文件或使用ALTER SYSTEM命令进行配置。
1. 日志输出配置
日志目标
ini
# 日志输出目标,可以是stderr、csvlog、syslog或eventlog(Windows)
log_destination = 'stderr' # 标准错误输出
# PostgreSQL 10+ 支持多目标输出
# log_destination = 'stderr,csvlog,syslog'
# 是否将日志输出到控制台(仅在前台运行时有效)
logging_collector = on # 开启日志收集器,将日志写入文件日志文件配置
ini
# 日志文件目录
log_directory = 'pg_log' # 相对路径(相对于data目录)或绝对路径
# 日志文件名称格式
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # 时间戳格式
# 日志文件轮换策略
log_rotation_age = 1d # 每天轮换一次
log_rotation_size = 100MB # 当文件大小超过100MB时轮换
# 保留的日志文件数量
log_truncate_on_rotation = on # 同一时间段的日志文件是否覆盖
log_filename = 'postgresql-%a.log' # 使用星期几作为文件名时,配合truncate使用
# 日志文件权限
log_file_mode = 0640 # 日志文件权限2. 日志格式配置
日志行前缀
ini
# 日志行前缀格式
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ' # 推荐格式
# 各参数含义:
# %t - 时间戳(格式:YYYY-MM-DD HH:MM:SS UTC)
# %p - 进程ID
# %l - 日志级别
# %u - 用户名
# %d - 数据库名
# %a - 应用程序名
# %h - 客户端主机名或IP地址
# %r - 客户端地址和端口
# %s - 会话ID
# %v - 虚拟事务ID
# %x - 事务ID
# %c - 命令类型
# %i - 命令标签
# %e - SQLSTATE错误代码
# %m - 错误信息
# %n - 换行符
# %b - 后台进程类型
# %q - 被截断的查询(如果log_truncate_on_rotation开启)日志格式选项
ini
# 是否在日志中包含进程启动时间
log_process_id = on
# 是否在日志中包含会话ID
log_session_identifier = on
# 是否在日志中包含行号
log_line_prefix = '%t [%p]: [%l-1] ' # 包含行号
# 是否在日志中包含应用程序名称
application_name = 'psql' # 客户端应用程序名称,由客户端设置3. 日志内容配置
日志级别
ini
# 日志级别,可选值:debug5, debug4, debug3, debug2, debug1, info, notice, warning, error, log, fatal, panic
log_min_messages = warning # 日志文件中的最小日志级别
client_min_messages = notice # 发送给客户端的最小日志级别
# 错误报告详细程度
log_error_verbosity = default # 可选值:terse, default, verbose
# 是否包含错误上下文信息
log_context_lines = 10 # 错误前后显示的上下文行数查询日志
ini
# 日志记录的语句类型,可选值:none, ddl, mod, all
log_statement = 'none' # 不记录任何语句
# log_statement = 'ddl' # 记录所有DDL语句
# log_statement = 'mod' # 记录所有DDL和DML语句
# log_statement = 'all' # 记录所有语句
# 记录执行时间超过指定毫秒数的语句
log_min_duration_statement = -1 # -1表示不记录,0表示记录所有语句,>0表示记录超过该时间的语句
# log_min_duration_statement = 1000 # 记录执行时间超过1秒的语句
# 是否记录语句参数
log_parameter_max_length = -1 # -1表示不限制,0表示不记录参数,>0表示记录参数的最大长度
log_parameter_max_length_on_error = -1 # 错误情况下记录参数的最大长度
# 是否记录锁等待
log_lock_waits = on # 记录等待时间超过deadlock_timeout的锁等待
# 是否记录死锁
log_deadlocks = on # 记录死锁信息连接与认证日志
ini
# 是否记录连接尝试
log_connections = on # 记录成功的连接
log_disconnections = on # 记录连接断开
# 是否记录认证失败信息
log_failed_connections = on # 记录认证失败的连接尝试
# 是否记录认证详细信息
log_hostname = on # 记录客户端主机名而不是IP地址WAL日志相关
ini
# 是否记录WAL归档信息
log_archive_command = 'cp %p /archive/%f' # WAL归档命令
log_archive_mode = on # 开启WAL归档日志
# 是否记录WAL回放信息(备库)
log_replication_commands = on # 记录复制相关命令
log_statement_stats = off # 关闭语句统计信息(性能影响大)4. 统计信息日志
ini
# 是否记录查询执行统计信息
log_statement_stats = off # 关闭,性能影响大
log_planner_stats = off # 关闭查询计划统计信息
log_executor_stats = off # 关闭执行器统计信息
# 是否记录缓冲区统计信息
log_buffer_stats = off # 关闭缓冲区统计信息
# 是否记录锁统计信息
log_lock_stats = off # 关闭锁统计信息
# 是否记录IO统计信息(PostgreSQL 13+)
log_io_stats = off # 关闭IO统计信息日志格式类型
PostgreSQL支持多种日志格式,包括文本格式、CSV格式和JSON格式。
1. 文本格式
文本格式是PostgreSQL默认的日志格式,易于阅读和分析。
2023-10-15 14:30:25 UTC [12345]: [1-1] user=postgres,db=mydb,app=psql,client=127.0.0.1 LOG: statement: SELECT * FROM users WHERE id = 1;
2023-10-15 14:30:25 UTC [12345]: [2-1] user=postgres,db=mydb,app=psql,client=127.0.0.1 LOG: duration: 1.234 ms statement: SELECT * FROM users WHERE id = 1;2. CSV格式
CSV格式适合使用电子表格或脚本工具进行分析。
ini
# 启用CSV日志
log_destination = 'csvlog'CSV日志格式示例:
2023-10-15 14:30:25.123 UTC,12345,1,postgres,mydb,psql,127.0.0.1,,LOG,00000,statement: SELECT * FROM users WHERE id = 1;,<none>,<none>,2023-10-15 14:30:25 UTC,12345,0,0
2023-10-15 14:30:25.124 UTC,12345,2,postgres,mydb,psql,127.0.0.1,,LOG,00000,duration: 1.234 ms statement: SELECT * FROM users WHERE id = 1;,<none>,<none>,2023-10-15 14:30:25 UTC,12345,0,03. JSON格式
从PostgreSQL 14开始,支持JSON格式日志,可以更方便地被日志分析工具处理。
ini
# 启用JSON日志格式
log_destination = 'stderr'
log_line_prefix = '' # 清空前缀
log_format = 'json' # 启用JSON格式JSON日志格式示例:
json
{
"timestamp": "2023-10-15 14:30:25 UTC",
"process_id": 12345,
"session_id": "652b9e81.3039",
"session_line_num": 1,
"command_tag": "SELECT",
"session_start_time": "2023-10-15 14:30:00 UTC",
"virtual_transaction_id": "3/456",
"transaction_id": 0,
"error_severity": "LOG",
"sql_state_code": "00000",
"message": "statement: SELECT * FROM users WHERE id = 1;",
"user_name": "postgres",
"database_name": "mydb",
"application_name": "psql",
"client_addr": "127.0.0.1",
"client_hostname": "localhost",
"client_port": 54321,
"backend_type": "client backend"
}日志配置最佳实践
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
# 查询日志配置
log_statement = 'ddl' # 记录DDL语句
log_min_duration_statement = 1000 # 记录执行时间超过1秒的语句
log_lock_waits = on # 记录锁等待
log_deadlocks = on # 记录死锁
# 连接与认证日志
log_connections = on
log_disconnections = on
log_failed_connections = on
log_hostname = off # 生产环境建议关闭,使用IP地址
# WAL相关日志
log_archive_command = 'cp %p /archive/%f'
log_replication_commands = on
# 统计信息日志(生产环境建议关闭)
log_statement_stats = off
log_planner_stats = off
log_executor_stats = off
log_buffer_stats = off
log_lock_stats = off
log_io_stats = off2. 开发/测试环境配置建议
ini
# 日志输出配置
log_destination = 'stderr,csvlog'
logging_collector = on
log_directory = 'pg_log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1h
log_rotation_size = 50MB
# 日志格式配置
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
# 日志内容配置
log_min_messages = info
client_min_messages = info
log_error_verbosity = verbose
log_context_lines = 20
# 查询日志配置
log_statement = 'all' # 记录所有语句
log_min_duration_statement = 0 # 记录所有语句的执行时间
log_lock_waits = on
log_deadlocks = on
# 连接与认证日志
log_connections = on
log_disconnections = on
log_failed_connections = on
log_hostname = on
# 统计信息日志(开发环境可以开启)
# log_statement_stats = on
# log_planner_stats = on
# log_executor_stats = on3. 慢查询日志配置
ini
# 慢查询日志配置
log_min_duration_statement = 500 # 记录执行时间超过500ms的语句
log_statement = 'none' # 不记录所有语句,只记录慢查询
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ' # 包含必要信息
log_error_verbosity = default
# PostgreSQL 13+ 支持将慢查询日志写入单独文件
# log_min_duration_sample = 1000 # 采样阈值
# log_statement_sample_rate = 0.1 # 采样率(10%)日志轮换与归档
1. 内置日志轮换
PostgreSQL内置了日志轮换功能,可以根据时间或大小进行日志轮换:
ini
# 基于时间的轮换
log_rotation_age = 1d # 每天轮换一次
# 基于大小的轮换
log_rotation_size = 100MB # 当文件大小超过100MB时轮换
# 日志文件数量限制
# PostgreSQL没有内置的日志文件数量限制,需要使用外部工具管理2. 使用外部工具进行日志管理
对于生产环境,建议使用外部工具如logrotate来管理日志文件:
logrotate配置示例
ini
# /etc/logrotate.d/postgresql
/var/log/postgresql/postgresql-*.log {
daily
rotate 7 # 保留7天的日志
compress # 压缩旧日志
delaycompress # 延迟压缩,保留最新的一个日志不压缩
missingok # 忽略不存在的文件
notifempty # 不压缩空文件
create 0640 postgres postgres # 创建新文件的权限和所有者
su postgres postgres # 以postgres用户身份运行
}配置cron定期清理日志
bash
# 每月1日清理30天前的日志
0 0 1 * * find /var/log/postgresql -name "postgresql-*.log" -mtime +30 -delete
0 0 1 * * find /var/log/postgresql -name "postgresql-*.log.gz" -mtime +365 -delete日志配置生效
1. 配置生效方式
sql
-- 方法1:修改postgresql.conf文件后重启PostgreSQL
-- 适用于需要重启才能生效的参数,如logging_collector
-- 方法2:使用ALTER SYSTEM命令(PostgreSQL 9.4+)
ALTER SYSTEM SET log_min_duration_statement = 500;
-- 方法3:使用pg_reload_conf()函数重载配置
SELECT pg_reload_conf();
-- 方法4:使用pg_ctl命令重载配置
pg_ctl reload -D /var/lib/postgresql/14/main2. 查看当前配置
sql
-- 查看所有日志相关配置
SELECT name, setting, unit, category, short_desc
FROM pg_settings
WHERE category LIKE '%Logging%' OR name LIKE '%log%';
-- 查看特定配置
SHOW log_destination;
SHOW logging_collector;
SHOW log_min_duration_statement;常见问题与解决方案
1. 日志文件不生成
问题:开启了logging_collector,但日志文件不生成
解决方案:
- 检查log_directory目录是否存在,权限是否正确
- 检查PostgreSQL进程是否有写权限
- 查看PostgreSQL错误日志,是否有相关错误信息
- 验证logging_collector是否真正开启:
SHOW logging_collector;
2. 日志文件权限问题
问题:无法查看日志文件,权限被拒绝
解决方案:
- 检查日志文件权限:
ls -l /var/log/postgresql/ - 确保当前用户属于postgres组:
groups $USER - 调整日志文件权限:
chmod 0644 /var/log/postgresql/*.log - 修改log_file_mode参数,设置合适的权限
3. 日志过大,占用过多磁盘空间
问题:日志文件增长过快,占用过多磁盘空间
解决方案:
- 调整log_rotation_age和log_rotation_size参数,增加轮换频率
- 减少日志级别,只记录必要的信息
- 关闭不必要的日志记录,如log_statement=none
- 使用logrotate等工具定期清理旧日志
- 考虑使用JSON格式日志,便于日志分析工具处理
4. 日志格式不符合要求
问题:日志格式不便于分析,缺少必要信息
解决方案:
- 调整log_line_prefix参数,包含必要的字段
- 考虑使用JSON格式日志,便于机器处理
- 确保log_process_id和log_session_identifier开启
5. 慢查询日志不记录
问题:设置了log_min_duration_statement,但慢查询不记录
解决方案:
- 检查log_min_duration_statement参数是否正确设置:
SHOW log_min_duration_statement; - 确保logging_collector开启
- 检查日志级别,确保慢查询的日志级别被记录
- 验证查询的执行时间是否确实超过了阈值
版本差异注意事项
PostgreSQL版本差异
| 版本 | 日志特性差异 |
|---|---|
| PostgreSQL 16 | 增强了JSON日志格式,支持更多字段 |
| PostgreSQL 15 | 改进了日志采样功能,支持更多采样选项 |
| PostgreSQL 14 | 引入了JSON日志格式,支持结构化日志 |
| PostgreSQL 13 | 增强了慢查询日志功能,支持采样和单独文件 |
| PostgreSQL 10 | 支持多目标日志输出 |
| PostgreSQL 9.4 | 引入了ALTER SYSTEM命令,支持在线修改配置 |
| PostgreSQL 9.3 | 引入了log_statement_stats等统计信息日志 |
日志参数变更
| 参数 | 版本 | 变更内容 |
|---|---|---|
| log_destination | 10+ | 支持多目标输出 |
| log_format | 14+ | 支持JSON格式 |
| log_min_duration_sample | 13+ | 新增参数,支持慢查询采样 |
| log_statement_sample_rate | 13+ | 新增参数,设置采样率 |
| log_replication_commands | 10+ | 新增参数,记录复制命令 |
| log_io_stats | 13+ | 新增参数,记录IO统计信息 |
总结
合理配置PostgreSQL日志是数据库运维的重要组成部分。通过优化日志配置,可以获得更有价值的日志信息,同时减少不必要的性能开销。在配置PostgreSQL日志时,需要根据实际环境(生产、开发、测试)和需求进行调整,平衡日志的详细程度和性能影响。
建议在生产环境中启用必要的日志记录,如DDL语句、慢查询、锁等待和死锁等,同时合理设置日志轮换策略,避免日志文件过大占用过多磁盘空间。对于日志分析,可以使用专业的日志分析工具如pgBadger、ELK Stack等,提高日志分析的效率和准确性。
