Skip to content

日志配置(log_destination / logging_collector) ​

从本页开始进入日志系统章节。PostgreSQL 的日志能力常被低估:它不只是「出了错打一行 ERROR」,而是一套可配置、可结构化、可对接外部系统的完整观测管道。慢查询、连接审计、死锁现场、autovacuum 行为、DDL 变更历史——生产环境的大量关键证据都写在日志里。日志配得好不好,直接决定故障时你是「翻证据」还是「猜原因」。

配置日志要回答三个问题:写到哪去(log_destination、logging_collector、文件命名与目录)、什么时候写(各级别阈值与慢语句阈值)、写多少细节(log_line_prefix、详细度、是否带语句原文)。本页聚焦「写到哪去」与「写多少细节」,轮转与清理留给下一页,CSV 与 JSON 两种结构化格式各有专页。

先建立一条主线:PostgreSQL 的日志参数分属 postgresql.conf 的 logging 区块,多数支持 reload 生效,但 logging_collector 等少数参数必须重启。改配置前先弄清每个参数的生效方式,避免「改了没生效」的困惑。

前置知识

建议先阅读:常用监控 SQL 汇总

基础概念 ​

PostgreSQL 的日志产生路径可以画成一条流水线:

text
后端进程/辅助进程产生消息
        │
        ├─ 消息级别低于阈值 ──► 丢弃
        │
        ▼
按 log_destination 决定去向
        │
        ├─ stderr ──► logging_collector = on ──► 收集进程写入日志文件
        │              logging_collector = off ─► 交给父进程(如 systemd journal)
        ├─ csvlog ──► 收集进程写入 CSV 文件(需 collector)
        ├─ jsonlog ─► 收集进程写入 JSON 文件(需 collector,PG15+)
        ├─ syslog ──► 交给系统 syslog 守护进程
        └─ eventlog ─► Windows 事件日志

核心概念有三个:

概念说明
logging_collector后台收集进程。开启后由它捕获所有进程的 stderr 并写入文件;修改需重启
log_destination消息去向,可同时逗号分隔配置多个
消息级别(severity)从 DEBUG5 到 PANIC 的分级体系,log_min_messages 控制入日志的下限

一个容易混淆的点:logging_collector 收集的是 stderr 流。log_destination = stderr 与 csvlog、jsonlog 的区别只是「写文件时用什么格式」——后两者必须经由收集进程落地,因此不能与 syslog/eventlog 混用(这两个去向绕过收集进程)。

消息级别体系 ​

服务器日志与客户端消息共用同一套级别,从低到高:

级别含义常见来源
DEBUG5 ~ DEBUG1开发调试信息,逐级更详细排查内核行为时临时开启
INFOVACUUM VERBOSE 等命令的显式输出用户命令
NOTICE提示性消息(如 CREATE TABLE 会转换列类型)用户命令
WARNING警告(潜在问题,语句仍成功)应用与运维命令
LOG服务器运行信息(检查点、连接、慢语句)服务器自身
ERROR当前语句失败语句错误
FATAL连接被终止(认证失败、后台崩溃)服务器
PANIC所有子进程崩溃罕见、严重

log_min_messages 的默认值是 warning,意味着默认日志里没有 LOG 级消息——而连接、检查点、慢语句统统是 LOG 级。生产库几乎一定要显式设置 log_min_messages,否则日志接近空白。

语法与用法 ​

最小生产配置 ​

conf
# postgresql.conf —— 日志基础配置的典型起点

# ---- 去向 ----
logging_collector = on                # 开启收集进程(修改需重启)
log_destination = 'csvlog'            # 结构化 CSV(或 'stderr' / 'jsonlog')

# ---- 文件位置与命名 ----
log_directory = 'log'                 # 相对于数据目录;也可写绝对路径
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_file_mode = 0600                  # 文件权限(非 Windows)

# ---- 记录什么 ----
log_min_messages = warning            # 低于 warning 的不进日志
log_min_error_statement = error       # ERROR 及以上附带语句原文
log_error_verbosity = default         # terse / default / verbose
log_connections = on                  # 连接建立时记录
log_disconnections = on               # 连接断开时记录
log_line_prefix = '%m [%p] %q%u@%d %r %b '   # 每行前缀,见下文

# ---- 轮转(下一页详解)----
log_rotation_age = 1d
log_rotation_size = 100MB
log_truncate_on_rotation = off
bash
# 修改后 reload 使多数参数生效
pg_ctl reload -D /var/lib/postgresql/18/main
# 或 SQL 方式
psql -c "SELECT pg_reload_conf();"

在线核对配置 ​

sql
-- 当前生效值
SHOW log_destination;
SHOW logging_collector;
SELECT name, setting, source, pending_restart
FROM pg_settings
WHERE name LIKE 'log_%'
ORDER BY name;

-- 配置文件里写了什么、是否生效
SELECT * FROM pg_file_settings WHERE name LIKE 'log_%';

pg_settings.pending_restart = true 表示该参数改了但要重启才生效——排查「改了没生效」的第一站。

详细说明 ​

log_destination 的五种去向 ​

取值说明依赖 collector
stderr写入 stderr(被收集进程捕获后写文件)写文件需要;否则交给父进程
csvlog以 CSV 格式写文件,固定 26 列结构是
jsonlog每条消息一个 JSON 对象(PG15+)是
syslog交给系统 syslog 守护进程否(绕过 collector)
eventlog写 Windows 事件日志(仅 Windows)否

要点:

  • 可以多选:log_destination = 'stderr,csvlog' 会同时写普通文本与 CSV 两套文件,适合过渡期。
  • csvlog/jsonlog 与 syslog 互斥使用:结构化格式由收集进程负责,syslog 是另一条通道。既要 syslog 又要结构化文件,就同时配置两者,靠不同管道各走各的。
  • 选型建议:要机器处理就选 csvlog 或 jsonlog(后者对现代日志栈更友好);只求人看,stderr + 合理前缀即可。
  • jsonlog 需要 PG15+;老版本只有前四种。

logging_collector 的进程模型 ​

logging_collector = on 时,Postmaster 会 fork 一个收集进程,所有后端把 stderr 写到管道,由收集进程统一落盘。行为要点:

  • 修改必须重启。这是 logging 区块里最常「改了不生效」的参数,检查 pg_settings.pending_restart。
  • 关闭时 stderr 直接继承给父进程:systemd 部署下消息进入 journal,容器部署下进入容器的 stdout。这不是「没有日志」,而是「日志由进程管理器接管」。
  • 收集进程自身很轻,但它是单点:日志盘 I/O 饱和时,消息会在管道里排队,极端情况下反压后端。日志目录必须与数据目录分盘,这是磁盘规划的硬规则。
  • 收集进程会把「多进程各自的 stderr」合并成单一文件流,这也是它存在的原因之一。

文件位置三件套:log_directory / log_filename / log_file_mode ​

conf
log_directory = 'log'                       # 相对数据目录,或绝对路径
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_file_mode = 0600
参数默认值说明
log_directorylog(较新版本;更早为 pg_log)相对路径基于数据目录
log_filenamepostgresql-%Y-%m-%d_%H%M%S.log支持 strftime 风格格式化符
log_file_mode0600八进制文件权限,Windows 上忽略

log_filename 的格式化符直接决定轮转行为,几个常用示例:

取值效果
postgresql-%Y-%m-%d.log按天一个文件
postgresql-%Y-%m-%d_%H.log按小时一个文件
postgresql-%Y-%m-%d_%H%M%S.log每次轮转产生新文件(默认值)
postgresql-%a.log按星期几循环覆盖(配合 log_truncate_on_rotation = on)

文件名里嵌入的时间精度与轮转周期要匹配:想要「按天+小时」的命名,就把 log_rotation_age 设为 1 小时;名字里没有时间变化,同一文件就会被反复追加(或配合 truncate 覆盖)。这套配合关系在《日志轮转与清理》一页展开。

log_min_messages 与级别阈值 ​

conf
log_min_messages = warning     # debug5..debug1, info, notice, warning, log, error, fatal, panic

语义:达到或高于设定级别的消息写入服务器日志。两个高频坑:

  1. 默认 warning 会滤掉所有 LOG 级消息,而连接日志、检查点、慢语句都是 LOG 级。生产常见做法是 log_min_messages = warning 保持不变、但显式开启需要的单项开关(log_connections 等会以 LOG 级输出吗?——会,单项开关输出的消息不受 log_min_messages 过滤)。若希望日志里出现全部运行信息,可设为 log 或 notice,代价是日志量增大。
  2. LOG 级别的排序在服务器端与客户端不一致:对服务器日志而言 LOG 总是排在 ERROR 之下、WARNING 之上附近的位置;对客户端而言它排在 FATAL 与 ERROR 之间。这是官方文档明确说明的特例,写级别比较逻辑时别踩。

单项开关(如 log_connections)产生的消息不受 log_min_messages 过滤,这是「保留 warning 阈值、同时获得连接日志」的标准姿势。

log_error_verbosity:消息详细度 ​

conf
log_error_verbosity = default    # terse / default / verbose
取值输出内容
terse级别 + 主文本 + 位置,抑制 DETAIL、HINT、QUERY、CONTEXT
default上述 + DETAIL / HINT / QUERY / CONTEXT 等字段
verbose再加 SQLSTATE 错误码、产生错误的源码文件/函数/行号(LOCATION)

排障场景(死锁、约束冲突分析)建议 verbose:死锁日志的 DETAIL 环描述、错误码都是分诊的关键。日志量大且已有 APM 收敛时可用 terse。

log_min_error_statement:错误时附带语句原文 ​

conf
log_min_error_statement = error

达到该级别(或更高)的错误会在日志中附带引发错误的 SQL 语句原文(截断到 2048 字符)。默认 error 意味着普通业务报错都会带语句——这对定位问题极有价值,但也意味着错误日志可能包含业务数据。敏感行业要评估该默认值,必要时收紧到 fatal,并配合权限与脱敏策略。

log_line_prefix:给每一行打上身份标签 ​

默认的 log_line_prefix 几乎为空(只有一个空格),导致多进程并发写日志时无法分辨「这行是谁写的」。生产环境必须配置它。全部转义符如下:

转义符含义
%aapplication_name
%u用户名
%d数据库名
%r远程主机名/IP 与端口(形如 host(54321))
%h远程主机名/IP
%b后端类型(backend_type,PG13+)
%p进程号 PID
%P并行组 leader 的 PID(PG14+;无则为空)
%t时间戳(不含毫秒)
%m时间戳(含毫秒)
%n时间戳(含毫秒,Unix epoch 格式)
%i命令标签(command tag,如 SELECT、UPDATE)
%eSQLSTATE 错误码
%c会话 ID(可关联同一会话的多行日志)
%l每个会话内的行号
%s进程启动时间戳
%v虚拟事务 ID(形如 3/4821)
%x事务 ID(无事务为 0)
%Q当前查询的 query ID(PG14+;未计算则为 0)
%q终止符:其后内容不输出给非会话进程(如后台进程)
%%字面 %

推荐的生产取值(兼顾可读性与机器解析):

conf
log_line_prefix = '%m [%p] %q%u@%d/%a %r %b '

%q 的用法要特别理解:放在 %q 之前的内容所有进程都输出,之后的内容只有普通会话进程输出。%c(会话 ID)是把一次连接产生的多行日志串起来的关键——日志平台的「会话视图」靠它实现。

连接与断开日志 ​

conf
log_connections = on     # 连接建立(含认证成功)时记录
log_disconnections = on  # 会话结束时记录(含时长)
log_duration = off       # 每条语句结束后记录执行时长(无语句内容)
  • log_connections / log_disconnections 是安全审计的基石,配置语义与完整示例见《log_connections / log_disconnections》一页。
  • log_duration 记录的是「每条语句一条时长日志」,与慢语句阈值(log_min_duration_statement)是两回事;后者按阈值过滤且可附带执行计划,是慢查询治理的主通道,相关细节由慢查询章节专门展开,本页不重复。
  • 连接风暴场景下这两个开关会让日志量暴涨,配合 log_connections 时要同时规划日志容量。

日志参数的生效方式速查 ​

参数生效方式
logging_collector重启
log_destinationreload
log_directory / log_filename / log_file_modereload(对新开的日志文件生效)
log_min_messages / log_error_verbosity / log_min_error_statementreload(可按会话覆盖部分)
log_line_prefixreload
log_connections / log_disconnections / log_durationreload(可按会话/角色覆盖)
log_rotation_age / log_rotation_size / log_truncate_on_rotationreload

配置生效方式的总方法论(reload 与 restart 的差别、ALTER SYSTEM)见《配置参数生效方式》一页。

syslog 专用参数 ​

选择 syslog 去向时,还有一组配套参数:

conf
syslog_facility = 'LOCAL0'          # syslog 设施(LOCAL0..LOCAL7),便于过滤
syslog_ident = 'postgres'           # syslog 标识
syslog_sequence_numbers = on        # 消息序号(便于发现丢失)
syslog_split_messages = on          # 按行拆分(默认按 900 字节拆,适配 syslog 行长限制)

syslog 通道的优点是复用系统级日志设施(集中收集、轮转交给 syslog 管理);缺点是消息被拆分、结构化字段丢失,且多一层守护进程的可靠性依赖。

两条时长通道:log_duration 与 log_min_duration_statement ​

记录语句耗时有两个参数,语义不同、叠加行为官方文档有明确定义:

参数记录什么是否带语句文本
log_duration = on每条完成的语句的耗时不带
log_min_duration_statement = 200耗时超过 200ms 的语句(设 0 则全部)带(超阈值时)

两者同时开启时:所有语句的耗时都会记录,但只有超过阈值的语句才附带语句文本。这个组合在高负载系统上很实用——耗时分位数靠全量时长日志,语句内容只对慢的保留:

conf
log_duration = on                       # 全量时长(不带文本)
log_min_duration_statement = 500        # 超过 500ms 的附语句文本

只有一个阈值需求时,单独用 log_min_duration_statement 即可;两者都开时要知道日志里同一慢语句会出现两条记录(一条带文本、一条纯时长),统计口径按需过滤。

log_parameter_max_length:绑定参数的截断控制 ​

语句日志默认会带上扩展协议语句的绑定参数值,由此带来两个反向需求:性能(大参数转文本的开销)与合规(参数值可能就是敏感数据)。PG13 引入的两个参数分别管两条通道:

参数作用范围默认值
log_parameter_max_length非错误语句日志(log_statement、时长日志等)-1(完整记录)
log_parameter_max_length_on_error错误消息中的参数0(不记录)
conf
# 高负载库的典型组合:时长日志截断大参数、错误消息不落参数
log_parameter_max_length = 64
log_parameter_max_length_on_error = 0

两个参数都是超级用户级设置(SUSET);非零值会带来「语句开始时就保存参数文本」的额外开销,扩展协议下更明显。需要完整参数值做重放调试时临时放开,用完收回。

按角色与会话覆盖日志行为 ​

日志参数大多支持按角色/会话覆盖,这把「全局一刀切」变成了「分而治之」:

sql
-- 报表角色:慢语句阈值收紧到 100ms,便于收集优化素材
ALTER ROLE report_user SET log_min_duration_statement = '100ms';

-- ETL 角色:批量操作的日志噪音单独关闭
ALTER ROLE etl_user SET log_statement = 'none';

-- 临时排查某个会话(仅本会话生效)
SET log_min_duration_statement = 0;

注意权限语义:log_min_duration_statement、log_statement 属于超级用户级参数,普通角色不能自行放宽;log_duration 等用户级参数可由会话调整。排查结束后记得清理会话级覆盖(RESET),并把角色级设置纳入配置版本管理。

application_name 的工程约定 ​

application_name 在日志(%a)、pg_stat_activity、CSV/JSON 日志里反复出现,是串联三者的关键标签。约定三条:

  1. 每个服务实例一个可识别的名字:形如 order-service-pool2,而不是所有服务共用驱动默认值。
  2. 连接池要透传:应用 → pgbouncer → 数据库的链路里确认 application_name 没有在中间被覆盖,否则日志标签失真。
  3. 与发布流水联动:把构建号拼进去(如 order-service@build-4821),「这条慢 SQL 来自哪个版本」直接可查。
bash
# 验证连接串设置的生效情况
psql "dbname=appdb application_name=dba-debug" \
  -c "SELECT application_name FROM pg_stat_activity WHERE pid = pg_backend_pid();"

systemd 与容器部署的日志归属 ​

logging_collector = off(默认)时,stderr 交给父进程,日志的「文件管理权」随之转移:

部署形态日志去向轮转责任人注意点
systemd(宿主机)journaldjournald(SystemMaxUse 等配额)journalctl -u postgresql 查询
Docker/K8s容器 stdout → json-file / 集群采集器Docker max-size/max-file 或平台单行一条,多行日志靠 stdout 编排
传统 sysv / 手工部署终端或文件需要自己接管这种形态建议直接开 collector 文件化

两种模式各有生态(journald 的持久化与检索、容器平台的采集管道),关键是全团队统一预期:不要出现「一半实例文件化、一半实例 stdout」的混合状态。容器形态的轮转与容量限制在《日志轮转与清理》里展开。

消息级别的完整阶梯 ​

日志参数大多围绕「级别」工作,完整阶梯(从详尽到严重):

级别语义服务器排序
DEBUG5 ~ DEBUG1开发调试信息,量最大最详细
LOG运行信息(检查点、连接、慢语句)详细
NOTICE / WARNING有用提示 / 潜在问题详细
ERROR当前命令失败中间
LOG(错误通道)后台运行信息(与上面的 LOG 是同一个词、不同位置)中间
FATAL连接中断严重
PANIC全体后端崩溃最严重

两个经典细节:LOG 在 log_min_messages 的服务器排序里出现两次(普通级别区与错误级别区各一个),导致「把 log_min_messages 设到 LOG 收不到 LOG」的困惑;客户端排序里 CLIENT_MIN_MESSAGES 的相邻关系又不同。拿不准时直接 SHOW log_min_messages; 看当前值,用 set_config 试验而不是硬背。

sql
-- 现场验证当前级别配置
SHOW log_min_messages;
SHOW client_min_messages;

log_checkpoints:让检查点写进日志(PG15+ 起默认开启) ​

检查点日志是「IO 抖动复盘」的第一手材料,PG15 起 log_checkpoints 默认 on:

text
LOG:  checkpoint starting: time
LOG:  checkpoint complete: wrote 20413 buffers (3.1%), wrote 3 WAL files, ...

checkpoint complete 行里有写缓冲数量、WAL 回收数量与耗时,配合 log_rotation_age 按时间轴归档后,就能回答「每晚 2 点的 IO 尖峰是不是检查点」。PG16 及以前该参数默认 off,升级到新版本时会「突然多出」这类日志,日志量预算要预留。

stderr 模式下的最小前缀推荐 ​

不开 logging_collector、把 stderr 交给 journald/容器时,log_line_prefix 是唯一的上下文载体。最小推荐:

conf
log_line_prefix = '%m [%p] %q%u@%d/%a '

拆解:时间 %m、进程号 %p、%q(无会话上下文时截断后半段)、用户 @ 库 / 应用名 + 空格。这五个要素让 journald/容器日志至少能完成「哪条消息属于哪个会话」的初筛。需要更细的排查再追加 %c(会话 ID)与 %x(事务 ID),但前缀越宽、每行体积越大,按需取舍。

特殊取值语义:0、-1 与关闭 ​

记录类参数的特殊值语义不一致,最容易记混的就是它们:

参数关闭全量说明
log_min_duration_statement-10(所有语句都算慢)单位 ms,正值是阈值
log_parameter_max_length-1 即不限制—正值是字符数上限
log_parameter_max_length_on_error0(不记录参数)-1与上面正好相反

「0 到底是关还是全量」取决于参数自己的定义,配置 review 时逐个对照官方文档,不要靠类比记忆。

运行时验证:配置真的生效了吗 ​

日志参数的生效方式不一(重启 / reload / 会话级),验证一步到位:

sql
-- 看当前值与来源(source 列显示是配置文件、会话还是角色级设置)
SELECT name, setting, source, pending_restart
FROM pg_settings
WHERE name IN ('logging_collector', 'log_destination', 'log_min_duration_statement',
               'log_line_prefix', 'log_duration')
ORDER BY name;

pending_restart = true 的参数(如 logging_collector)改了也不会 reload 生效,必须安排重启窗口;source = 'session' 说明被会话级覆盖过——排查「日志行为与配置文件不一致」时,这个查询就是答案。

实战示例 ​

示例一:从零配置一个可生产的日志基线 ​

conf
# 1) 开启收集器与结构化格式(重启生效)
logging_collector = on
log_destination = 'csvlog'

# 2) 文件命名:按天 + 每次启动新建
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d.log'

# 3) 让每行可溯源
log_line_prefix = '%m [%p] %q%u@%d %r %b '

# 4) 记录内容
log_min_messages = warning
log_error_verbosity = verbose
log_min_error_statement = error
log_connections = on
log_disconnections = on

# 5) 轮转兜底:单文件不超过 100MB
log_rotation_size = 100MB
bash
# 6) 重启使 collector 生效,随后验证
pg_ctl restart -D /var/lib/postgresql/18/main
psql -c "SHOW logging_collector;"
text
 logging_collector
-------------------
 on
(1 row)
bash
# 7) 确认日志目录与文件
ls -l $PGDATA/log/
text
-rw------- 1 postgres postgres  20480 Sep 30 10:15 postgresql-2026-09-30.log

示例二:验证一条错误日志的完整信息 ​

sql
-- 制造一条带详细信息的错误
SELECT 1/0;
text
2026-09-30 10:20:01.123 CST [18241] app@appdb 10.0.0.11(51022) client backend ERROR:  division by zero
2026-09-30 10:20:01.123 CST [18241] app@appdb 10.0.0.11(51022) client backend STATEMENT:  SELECT 1/0;

verbose 级别下还会有 SQLSTATE(如 22012 除零)与 LOCATION 行。用 log_line_prefix 里的会话 ID(%c)可以把同一连接的 ERROR、STATEMENT、DETAIL 串成一组。

示例三:syslog 通道的最小接入 ​

conf
log_destination = 'syslog'
syslog_facility = 'LOCAL0'
syslog_ident = 'pg-main'
bash
# rsyslog 侧按 facility 过滤到独立文件
echo "local0.*  /var/log/postgresql/main.log" >> /etc/rsyslog.d/30-postgresql.conf
systemctl reload rsyslog

之后由 syslog 生态统一负责转发与轮转,PostgreSQL 侧不再管理文件。

示例四:按角色差异化日志策略 ​

目标:OLTP 应用安静、报表可观测、DBA 会话全量留痕。

conf
# 全局基线:安静,只留错误与必要审计
log_min_messages = warning
log_min_duration_statement = 1s
log_error_verbosity = verbose
log_connections = off
log_disconnections = off
sql
-- 报表角色:100ms 阈值 + 连接审计(角色级覆盖)
ALTER ROLE report_user SET log_min_duration_statement = '100ms';
ALTER ROLE report_user SET log_connections = on;
ALTER ROLE report_user SET log_disconnections = on;

-- DBA 运维角色:全语句记录(仅该角色,评估日志量后使用)
ALTER ROLE dba_ops SET log_statement = 'all';
ALTER ROLE dba_ops SET log_min_duration_statement = 0;

-- 验证生效
SELECT rolname, rolconfig FROM pg_roles
WHERE rolname IN ('report_user', 'dba_ops', 'app_user');
text
   rolname   |                         rolconfig
-------------+----------------------------------------------------------
 report_user | {log_min_duration_statement=100ms,log_connections=on,...}
 dba_ops     | {log_statement=all,log_min_duration_statement=0}
 app_user    |
(3 rows)

这套策略的前提是角色划分清晰(应用、报表、运维各自独立角色);日志量按角色评估,报表与 DBA 角色的日志增量单独观察三天再定稿。

示例五:两分钟排障——日志为什么没有输出 ​

改了配置却没有日志,按固定顺序排查,通常两分钟内定位:

sql
-- 1) 输出去向对不对?
SHOW log_destination;          -- 期望含 csvlog / jsonlog
SHOW logging_collector;        -- 期望 on

-- 2) 改动是否还在等重启?
SELECT name, setting, pending_restart
FROM pg_settings
WHERE name IN ('logging_collector', 'log_destination');

-- 3) 级别门是不是全关了?
SHOW log_min_messages;         -- warning 会吞掉 LOG 级消息
SHOW log_min_duration_statement;
bash
# 4) 目录与权限
SHOW log_directory;
ls -la /var/lib/postgresql/18/main/log/ | head

四步覆盖了「目的地、生效方式、级别门、文件系统」的全部常见断点:log_min_messages = warning 是最隐蔽的一个——它会把连接审计、慢语句这些 LOG 级消息全部静默。

注意事项 ​

logging_collector 改动必须重启。 它是「配置了却一直没生效」的高发区。改完用 pg_settings.pending_restart 核对,别反复 reload 无效配置。

日志盘与数据盘必须分离。 收集进程写日志的 I/O 与数据库 I/O 混盘时,日志风暴会直接拖垮数据读写;反之数据盘打满也会连累日志。规划层面就要分开。

log_line_prefix 默认近乎为空。 不配置前缀的多进程日志基本不可分析。哪怕只用 %m [%p] ,也让每行有了时间与进程身份。

log_min_messages 与单项开关是两套逻辑。 单项开关(log_connections 等)不受级别阈值过滤;想要连接日志不需要把阈值降到 log。反过来,把阈值设成 debug1 会产生海量日志,只用于短时排查。

默认日志名带 %H%M%S,每次轮转都是新文件。 想要按天合并文件需要显式改 log_filename;「日志文件怎么这么多」多半是这个原因,轮转策略见下一页。

CSV/JSON 与 syslog 不能混为一谈。 csvlog、jsonlog 只能由收集进程写文件;配置了 syslog 的实例不会产生结构化文件。既要集中收集又要结构化,用 syslog 收集后再解析,或让日志采集 agent 直接读结构化文件。

错误日志会包含语句原文。 log_min_error_statement = error 下,业务报错的 SQL 会进日志,其中的常量可能就是敏感数据。合规要求严格的系统要评估级别、加密日志存储并限制访问权限。

容器与 systemd 部署有额外一层。 logging_collector = off 时日志进 journal/容器 stdout,多数云环境反而推荐这种「交给进程管理器」的模式;本页的文件化配置主要面向传统部署。两种模式不要混用同一套预期。

最佳实践 ​

  1. 生产库必配 log_line_prefix,且包含 %m [%p] %q%u@%d %b。 时间、进程、用户、数据库、后端类型是所有日志分析的最小需求;需要会话串联就加 %c。
  2. 结构化日志优先选 csvlog 或 jsonlog。 有现代日志栈(ELK/Loki)直接选 jsonlog(PG15+)或 csvlog;前者对采集器最友好,格式细节见后续两页。
  3. 保持 log_min_messages = warning,用单项开关定制内容。 避免整体降级产生海量日志;需要什么(连接、autovacuum、检查点)就开对应开关。
  4. 错误详细度用 verbose。 SQLSTATE 与 DETAIL/HINT 是自动化分诊的原料,详细度换来的日志增量完全值得。
  5. 连接审计标配 log_connections + log_disconnections。 结合本站的审计专题页做留存策略;连接风暴时它能给出「谁在连」的直接证据。
  6. 日志目录独立磁盘、独立容量监控。 日志盘使用率告警阈值要比数据盘更严(如 70%),因为日志增速最难预测。
  7. 改日志配置先核对生效方式。 用 pg_settings 的 source 与 pending_restart 字段确认配置来源与是否需要重启,减少无效折腾。
  8. 错误语句原文的合规评估前置。 确定保留 log_min_error_statement = error 之前,先过一遍数据分级;必要时收紧级别并用日志侧加密与访问控制补偿。
  9. 容器部署明确日志归属。 明确「collector 文件化」还是「stdout 交给平台」,并在文档里写死,避免两套预期并存。
  10. 每次变更后用真实消息验证格式。 制造一条已知错误(如 SELECT 1/0),检查时间戳、前缀、级别、语句原文都符合预期,再收工。

下一节

继续学习:日志轮转与清理

参考链接 ​