纲要
logging_collector:日志收集器log_destination:日志输出目标log_directory:日志目录log_filename:日志文件名格式log_rotation_age:日志轮转时间阈值log_rotation_size:日志轮转大小阈值log_truncate_on_rotation:日志轮转截断策略log_connections/log_disconnections:连接日志log_autovacuum_min_duration:autovacuum 日志阈值log_checkpoints:检查点日志log_lock_waits:锁等待日志log_temp_files:临时文件日志log_min_duration_statement:慢查询阈值log_duration:查询时长日志log_statement:语句类型日志log_min_duration_sample/log_statement_sample_rate:日志采样(pg 14+)log_line_prefix:日志行前缀自定义log_min_messages/client_min_messages:消息级别控制file_fdw:文件外部数据包装器
日志架构概览
postgresql 的日志系统由 logging_collector 后台进程统一管理。该进程捕获发送到 stderr 的日志消息并将其重定向至日志文件。所有日志相关参数均在 postgresql.conf 中配置,修改后可通过 pg_reload_conf() 或 select pg_reload_conf() 动态加载(部分参数需重启)。
日志基础配置
日志输出目标与目录
log_destination 控制日志输出目标,支持 stderr、csvlog、jsonlog 和 syslog(windows 额外支持 eventlog),可组合使用:
# postgresql.conf logging_collector = on log_destination = 'stderr,csvlog' log_directory = 'pg_log'
log_directory 指定日志文件目录,可为绝对路径或相对于 pgdata 的路径。
日志文件名与轮转策略
log_filename 支持 strftime 格式占位符:
log_filename = 'postgresql-%y-%m-%d_%h%m%s.log' log_rotation_age = 1d log_rotation_size = 100mb log_truncate_on_rotation = off
log_rotation_age:单个日志文件的最大生命周期(分钟),设为0禁用基于时间的轮转log_rotation_size:单个日志文件的最大大小(kb),设为0禁用基于大小的轮转log_truncate_on_rotation:轮转时是否截断(覆盖)而非追加已存在的同名文件
pgdata/pg_log/ ├── postgresql-2026-08-21_000000.log ├── postgresql-2026-08-21_120000.log └── postgresql-2026-08-22_000000.log
连接日志
log_connections 和 log_disconnections 控制客户端连接事件的记录,包含来源 ip、端口、应用名称等信息,对排查连接风暴和异常访问源至关重要:
log_connections = on log_disconnections = on
启用后日志示例:
log: connection received: host=192.168.1.100 port=54321 log: connection authorized: user=app_user database=app_db log: disconnection: session time: 0:00:05.123 user=app_user database=app_db host=192.168.1.100 port=54321
autovacuum 与检查点日志
log_autovacuum_min_duration 设置 autovacuum 操作的日志阈值(毫秒),超过该阈值的操作将被记录:
log_autovacuum_min_duration = 1000 # 记录超过1秒的autovacuum操作
log_checkpoints 控制检查点事件的日志记录:
log_checkpoints = on
检查点日志示例包含脏页数量、写入时长和内存使用等信息,是分析 i/o 性能的重要依据。
锁等待与临时文件日志
log_lock_waits 控制在会话等待锁超过 deadlock_timeout 时是否产生日志:
log_lock_waits = on deadlock_timeout = 1s
log_temp_files 控制临时文件的日志记录。当查询的 work_mem 不足时,数据会溢出到磁盘临时文件:
log_temp_files = 0 # 记录所有临时文件
该参数值为 kb 单位,设为 0 记录所有临时文件,正数仅记录大于等于该值的文件,-1 禁用。结合临时文件日志可合理调整 work_mem。
慢查询日志
log_min_duration_statement
最常用的慢查询控制参数,设置语句执行时间阈值(毫秒),超过该阈值的语句将在执行完成后连同耗时一并记录:
log_min_duration_statement = 500 # 记录超过500ms的查询
- 设为
0:记录所有语句及其耗时 - 设为
-1(默认):禁用
该参数记录查询文本,适合生产环境定位慢查询。
log_duration
记录所有已完成语句的耗时,不记录查询文本:
log_duration = on
log_duration 只有 on/off,无法按阈值过滤。两者同时启用时,log_min_duration_statement 的优先级更高。
log_duration = on log_min_duration_statement = 500
– 所有语句的耗时均被记录,但仅超过 500ms 的语句包含查询文本
语句类型日志
log_statement 控制哪些类型的 sql 语句被记录:
log_statement = 'ddl' # 默认值
可选值:
none(默认):不记录任何语句ddl:记录 ddl 语句(create、alter、drop等)mod:记录 ddl 及数据修改语句(insert、update、delete、truncate、copy from)all:记录所有语句
log_statement 在语句被正确解析后即记录。与 log_min_duration_statement 配合使用时,已被 log_statement 记录的查询不会被重复记录。
日志采样(postgresql 14+)
高并发场景下记录所有语句会带来显著性能开销和日志量压力。pg 14 引入采样机制:
log_min_duration_sample:采样阈值(毫秒),仅超过该阈值的语句才进入采样池log_statement_sample_rate:采样率(0.0 ~ 1.0)
log_min_duration_sample = 100 log_statement_sample_rate = 0.5
记录所有执行时间超过 100ms 的语句中 50% 的样本。
与 log_min_duration_statement 配合时,后者的优先级更高:
log_min_duration_statement = 500 log_min_duration_sample = 100 log_statement_sample_rate = 0.1
– 记录所有超过 500ms 的查询;同时采样记录超过 100ms 查询中的 10%
自定义日志格式
log_line_prefix 是 printf 风格的字符串,用于自定义日志行前缀:
log_line_prefix = '%m [%p] %q%u@%d/%a '
常用转义符:
%m:带毫秒的时间戳%p:进程 id(pid)%u:用户名%d:数据库名%a:应用名称%h:客户端主机%r:客户端主机和端口%q:会话上下文分隔符
消息级别控制
log_min_messages 控制写入服务器日志的消息级别:
log_min_messages = 'warning'
client_min_messages 控制发送到客户端的消息级别:
client_min_messages = 'notice'
级别从低到高(低级别输出更详细):debug5 < debug4 < … < debug1 < log < notice < warning < error。
file_fdw:用 sql 查询日志
file_fdw 是 postgresql 官方 contrib 模块,允许将文件系统中的文件映射为外部表:
-- 创建扩展
create extension file_fdw;
-- 创建外部服务器
create server file_server foreign data wrapper file_fdw;
-- 创建外部表(以csv格式日志为例)
create foreign table pg_log (
log_time timestamp(3) with time zone,
user_name text,
database_name text,
process_id integer,
connection_from text,
session_id text,
session_line_num bigint,
command_tag text,
session_start_time timestamp with time zone,
virtual_transaction_id text,
transaction_id bigint,
error_severity text,
sql_state_code text,
message text,
detail text,
hint text,
internal_query text,
internal_query_pos integer,
context text,
query text,
query_pos integer,
location text,
application_name text
) server file_server
options (filename '/path/to/pg_log/postgresql.csv', format 'csv');
之后即可用标准 sql 查询日志:
select log_time, user_name, database_name, query from pg_log where error_severity = 'error' and log_time > current_timestamp - interval '1 hour' order by log_time desc;
使用 file_fdw 需具备 pg_read_server_files 角色权限。
api 速览
| 参数 | 类型 | 默认值 | 适用版本 | 说明 |
|---|---|---|---|---|
logging_collector | boolean | off | 全部 | 启用日志收集器 |
log_destination | string | stderr | 全部 | 日志输出目标 |
log_directory | string | pg_log | 全部 | 日志目录 |
log_filename | string | postgresql-%y-%m-%d_%h%m%s.log | 全部 | 日志文件名格式 |
log_rotation_age | integer | 1440 | 全部 | 轮转时间阈值(分钟) |
log_rotation_size | integer | 10240 | 全部 | 轮转大小阈值(kb) |
log_truncate_on_rotation | boolean | off | 全部 | 轮转时是否截断 |
log_connections | boolean | off | 全部 | 记录连接事件 |
log_disconnections | boolean | off | 全部 | 记录断开事件 |
log_autovacuum_min_duration | integer | -1 | 全部 | autovacuum 日志阈值(ms) |
log_checkpoints | boolean | off | 全部 | 记录检查点 |
log_lock_waits | boolean | off | 全部 | 记录锁等待 |
log_temp_files | integer | -1 | 全部 | 临时文件日志阈值(kb) |
log_min_duration_statement | integer | -1 | 全部 | 慢查询阈值(ms) |
log_duration | boolean | off | 全部 | 记录所有语句耗时 |
log_statement | enum | none | 全部 | 语句类型过滤 |
log_min_duration_sample | integer | -1 | 14+ | 采样阈值(ms) |
log_statement_sample_rate | float | 1.0 | 14+ | 采样率(0.0~1.0) |
log_line_prefix | string | ‘’ | 全部 | 日志行前缀 |
log_min_messages | enum | warning | 全部 | 服务器日志级别 |
client_min_messages | enum | notice | 全部 | 客户端消息级别 |
demo 完整示例
以下 demo 演示如何在 node.js 应用中配置 postgresql 慢查询日志,并使用 file_fdw 查询日志进行分析。
运行说明
环境要求:
- postgresql 14+
- node.js 16+
pgnpm 包
步骤:
- 配置
postgresql.conf:
logging_collector = on log_destination = 'stderr,csvlog' log_directory = 'pg_log' log_filename = 'postgresql-%y-%m-%d_%h%m%s.log' log_rotation_age = 1d log_rotation_size = 100mb log_min_duration_statement = 500 log_connections = on log_disconnections = on log_lock_waits = on log_temp_files = 0 log_line_prefix = '%m [%p] %q%u@%d/%a '
- 重启 postgresql 使配置生效:
sudo systemctl restart postgresql # 或 pg_ctl restart -d /path/to/data
- 安装依赖并运行 demo:
npm init -y npm install pg node demo.js
代码说明
// demo.js
const { client } = require('pg');
const pg_config = {
host: 'localhost',
port: 5432,
database: 'testdb',
user: 'testuser',
password: 'testpass'
};
// 创建带慢查询的测试数据
async function setuptestdata(client) {
await client.query(`
create table if not exists test_logging (
id serial primary key,
data text,
created_at timestamp default now()
)
`);
// 插入 10000 条测试数据
await client.query(`
insert into test_logging (data)
select md5(random()::text)
from generate_series(1, 10000)
`);
console.log('[setup] 测试数据已创建');
}
// 执行一个慢查询(模拟)
async function runslowquery(client) {
const start = date.now();
await client.query(`
select count(*), data
from test_logging
group by data
having count(*) > 1
order by count(*) desc
`);
const duration = date.now() - start;
console.log(`[query] 慢查询执行完成,耗时: ${duration}ms`);
}
// 使用 file_fdw 查询日志(需提前配置)
async function querylogswithfilefdw(client) {
// 创建 file_fdw 扩展
await client.query('create extension if not exists file_fdw');
// 创建外部服务器
await client.query(`
create server if not exists log_server
foreign data wrapper file_fdw
`);
// 创建外部表(csv格式)
await client.query(`
create foreign table if not exists pg_log_csv (
log_time timestamp(3) with time zone,
user_name text,
database_name text,
process_id integer,
connection_from text,
session_id text,
session_line_num bigint,
command_tag text,
session_start_time timestamp with time zone,
virtual_transaction_id text,
transaction_id bigint,
error_severity text,
sql_state_code text,
message text,
detail text,
hint text,
internal_query text,
internal_query_pos integer,
context text,
query text,
query_pos integer,
location text,
application_name text
) server log_server
options (filename '/path/to/pg_data/pg_log/postgresql.csv', format 'csv')
`);
// 查询最近1小时的慢查询
const result = await client.query(`
select
log_time,
user_name,
database_name,
substring(query, 1, 100) as query_preview,
message
from pg_log_csv
where error_severity = 'log'
and message like '%duration%'
and log_time > now() - interval '1 hour'
order by log_time desc
limit 10
`);
console.log('[logs] 最近慢查询:');
result.rows.foreach(row => {
console.log(` ${row.log_time} | ${row.user_name} | ${row.query_preview}...`);
});
}
async function main() {
const client = new client(pg_config);
try {
await client.connect();
console.log('[demo] 已连接到 postgresql');
await setuptestdata(client);
// 执行多次慢查询以便产生日志
for (let i = 0; i < 3; i++) {
await runslowquery(client);
}
// 查询日志(需将路径替换为实际日志路径)
// await querylogswithfilefdw(client);
// 查看当前慢查询配置
const config = await client.query(`
select name, setting
from pg_settings
where name in (
'log_min_duration_statement',
'log_duration',
'log_statement',
'logging_collector'
)
`);
console.log('[config] 当前日志配置:');
config.rows.foreach(row => {
console.log(` ${row.name} = ${row.setting}`);
});
} catch (err) {
console.error('[error]', err);
} finally {
await client.end();
}
}
main();技术点总结
log_min_duration_statement用于捕获超过阈值的慢查询logging_collector是日志持久化的前提log_line_prefix自定义日志格式便于解析file_fdw将日志文件映射为外部表,用 sql 分析日志- 通过
pg_settings视图可查看当前运行时配置
postgresql 原生指令对照
-- 查看当前慢查询阈值 show log_min_duration_statement; -- 动态修改(当前会话) set log_min_duration_statement = 1000; -- 动态修改(全局,下次连接生效) alter system set log_min_duration_statement = '1000'; select pg_reload_conf(); -- 查看日志相关所有参数 select name, setting, unit, context from pg_settings where name like 'log%' order by name;
多语言示例
以下分别使用 go、python 和 java 实现与 node.js 示例相同的功能:连接 postgresql、创建测试表、插入测试数据、执行慢查询并查看日志配置。
go 示例
运行说明
环境要求:
- go 1.19+
- postgresql 14+
- 驱动:
github.com/lib/pq
步骤:
- 初始化模块并安装依赖:
go mod init demo go get github.com/lib/pq
- 确保
postgresql.conf已按前文配置,并重启 postgresql。 - 运行:
go run demo.go
代码说明
// demo.go
package main
import (
"database/sql"
"fmt"
"log"
"time"
_ "github.com/lib/pq"
)
const (
host = "localhost"
port = 5432
user = "testuser"
password = "testpass"
dbname = "testdb"
)
func main() {
connstr := fmt.sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
db, err := sql.open("postgres", connstr)
if err != nil {
log.fatal("连接失败:", err)
}
defer db.close()
if err := db.ping(); err != nil {
log.fatal("ping失败:", err)
}
fmt.println("[demo] 已连接到 postgresql")
// 创建测试表
_, err = db.exec(`
create table if not exists test_logging (
id serial primary key,
data text,
created_at timestamp default now()
)
`)
if err != nil {
log.fatal("建表失败:", err)
}
// 插入测试数据
_, err = db.exec(`
insert into test_logging (data)
select md5(random()::text)
from generate_series(1, 10000)
`)
if err != nil {
log.fatal("插入数据失败:", err)
}
fmt.println("[setup] 测试数据已创建")
// 执行慢查询(重复3次)
for i := 0; i < 3; i++ {
start := time.now()
rows, err := db.query(`
select count(*), data
from test_logging
group by data
having count(*) > 1
order by count(*) desc
`)
if err != nil {
log.fatal("查询失败:", err)
}
rows.close()
duration := time.since(start)
fmt.printf("[query] 慢查询执行完成,耗时: %v\n", duration)
}
// 查看当前慢查询配置
var name, setting string
rowscfg, err := db.query(`
select name, setting
from pg_settings
where name in ('log_min_duration_statement', 'log_duration', 'log_statement', 'logging_collector')
`)
if err != nil {
log.fatal("查询配置失败:", err)
}
defer rowscfg.close()
fmt.println("[config] 当前日志配置:")
for rowscfg.next() {
rowscfg.scan(&name, &setting)
fmt.printf(" %s = %s\n", name, setting)
}
}技术点总结
- 使用
lib/pq驱动连接 postgresql,dsn 格式标准 sql.open返回连接池,ping验证连通性- 批量插入使用
generate_series生成测试数据 - 执行慢查询(分组聚合)模拟耗时操作
- 查询
pg_settings视图获取当前日志参数
python 示例
运行说明
环境要求:
- python 3.8+
- postgresql 14+
- 驱动:
psycopg2-binary
步骤:
- 安装依赖:
pip install psycopg2-binary
- 确保 postgresql 配置正确并重启。
- 运行:
python demo.py
代码说明
# demo.py
import psycopg2
import time
pg_config = {
'host': 'localhost',
'port': 5432,
'database': 'testdb',
'user': 'testuser',
'password': 'testpass'
}
def main():
conn = psycopg2.connect(**pg_config)
conn.autocommit = true
cur = conn.cursor()
print("[demo] 已连接到 postgresql")
# 创建测试表
cur.execute("""
create table if not exists test_logging (
id serial primary key,
data text,
created_at timestamp default now()
)
""")
# 插入测试数据
cur.execute("""
insert into test_logging (data)
select md5(random()::text)
from generate_series(1, 10000)
""")
print("[setup] 测试数据已创建")
# 执行慢查询(重复3次)
for i in range(3):
start = time.time()
cur.execute("""
select count(*), data
from test_logging
group by data
having count(*) > 1
order by count(*) desc
""")
rows = cur.fetchall()
duration = (time.time() - start) * 1000
print(f"[query] 慢查询执行完成,耗时: {duration:.2f}ms")
# 查看当前慢查询配置
cur.execute("""
select name, setting
from pg_settings
where name in ('log_min_duration_statement', 'log_duration', 'log_statement', 'logging_collector')
""")
print("[config] 当前日志配置:")
for name, setting in cur.fetchall():
print(f" {name} = {setting}")
cur.close()
conn.close()
if __name__ == "__main__":
main()技术点总结
- 使用
psycopg2驱动,autocommit=true避免显式事务 - 游标执行 ddl 和 dml,
fetchall获取结果 time.time()测量执行耗时(毫秒转换)- 查询
pg_settings查看运行时配置
java 示例
运行说明
环境要求:
- jdk 11+
- postgresql 14+
- maven 或手动添加依赖:
org.postgresql:postgresql:42.7.3
步骤:
- 创建 maven 项目,在
pom.xml中添加:
<dependency>
<groupid>org.postgresql</groupid>
<artifactid>postgresql</artifactid>
<version>42.7.3</version>
</dependency>- 编译并运行:
mvn compile mvn exec:java -dexec.mainclass="demo"
或直接使用 javac 和 java(需将 jar 加入 classpath)。
代码说明
// demo.java
import java.sql.*;
import java.util.properties;
public class demo {
private static final string url = "jdbc:postgresql://localhost:5432/testdb";
private static final string user = "testuser";
private static final string password = "testpass";
public static void main(string[] args) {
properties props = new properties();
props.setproperty("user", user);
props.setproperty("password", password);
try (connection conn = drivermanager.getconnection(url, props)) {
system.out.println("[demo] 已连接到 postgresql");
// 创建测试表
try (statement stmt = conn.createstatement()) {
stmt.execute("""
create table if not exists test_logging (
id serial primary key,
data text,
created_at timestamp default now()
)
""");
// 插入测试数据
stmt.execute("""
insert into test_logging (data)
select md5(random()::text)
from generate_series(1, 10000)
""");
system.out.println("[setup] 测试数据已创建");
}
// 执行慢查询(重复3次)
for (int i = 0; i < 3; i++) {
long start = system.currenttimemillis();
try (statement stmt = conn.createstatement();
resultset rs = stmt.executequery("""
select count(*), data
from test_logging
group by data
having count(*) > 1
order by count(*) desc
""")) {
while (rs.next()) {
// 消费结果集
}
}
long duration = system.currenttimemillis() - start;
system.out.printf("[query] 慢查询执行完成,耗时: %dms%n", duration);
}
// 查看当前慢查询配置
try (statement stmt = conn.createstatement();
resultset rs = stmt.executequery("""
select name, setting
from pg_settings
where name in ('log_min_duration_statement', 'log_duration', 'log_statement', 'logging_collector')
""")) {
system.out.println("[config] 当前日志配置:");
while (rs.next()) {
system.out.printf(" %s = %s%n", rs.getstring("name"), rs.getstring("setting"));
}
}
} catch (sqlexception e) {
e.printstacktrace();
}
}
}技术点总结
- 使用 jdbc 驱动,url 格式
jdbc:postgresql://host:port/db - 通过
properties传递认证信息 - 使用 try-with-resources 自动释放资源(
statement、resultset、connection) system.currenttimemillis()测量毫秒级耗时- 查询
pg_settings与 node.js 示例逻辑一致
多语言对比
| 特性 | node.js (pg) | go (lib/pq) | python (psycopg2) | java (jdbc) |
|---|---|---|---|---|
| 连接方式 | new client(config) | sql.open("postgres", dsn) | psycopg2.connect(**config) | drivermanager.getconnection(url, props) |
| 连接池 | 默认支持(内置) | 默认支持(sql.db) | 需要额外配置(threadedconnectionpool) | 需要额外库(如 hikaricp) |
| 执行查询 | client.query() | db.query() | cur.execute() | stmt.executequery() |
| 参数化查询 | $1, $2 | $1, $2 | %s(或 %(name)s) | ? 或 $1(pg 驱动支持 $1) |
| 事务控制 | 默认自动提交,可手动 begin | 默认自动提交,可 db.begin() | autocommit 参数控制 | 默认自动提交,conn.setautocommit(false) |
| 错误处理 | try/catch | 返回 error | try/except | try/catch (sqlexception) |
| 资源释放 | 客户端 end() | defer rows.close() | cur.close() / conn.close() | try-with-resources 自动关闭 |
| 类型映射 | 自动映射 json/数组 | 需实现 scanner 接口 | 自动映射 python 类型 | 需通过 getxxx 获取 |
| 日志配置查看 | 查询 pg_settings | 查询 pg_settings | 查询 pg_settings | 查询 pg_settings |
| 适用场景 | 快速开发、原型 | 高并发、微服务 | 数据分析、脚本 | 企业级应用、spring 生态 |
所有示例均实现了相同的功能:连接 → 建表 → 批量插入 → 执行慢查询(重复3次)→ 读取日志配置。用户可根据自身技术栈选择对应语言,核心逻辑与 postgresql 交互方式一致,仅驱动 api 和语法风格不同。
总结
本文系统梳理了 postgresql 日志体系的全部核心参数,涵盖日志输出与轮转、连接审计、autovacuum 与检查点监控、锁等待与临时文件诊断、慢查询捕获、语句类型过滤、高并发场景下的采样机制以及自定义日志格式等维度。
生产环境应根据负载特征合理配置 log_min_duration_statement(慢查询阈值)和 log_statement(语句类型),高并发场景可启用 pg 14+ 的采样参数 log_min_duration_sample 与 log_statement_sample_rate 平衡性能开销与可观测性。
file_fdw 提供了用 sql 分析日志的创新途径,大幅提升日志分析的灵活性和效率。所有配置变更需通过 postgresql.conf 或 alter system 持久化,并调用 pg_reload_conf() 动态生效。
以上就是postgresql慢查询日志配置与日志管理完全指南的详细内容,更多关于postgresql慢查询日志配置与管理的资料请关注代码网其它相关文章!
发表评论