在 PostgreSQL (PG) 数据库中,参数能否在不重启的情况下修改,取决于该参数的 Context (上下文) 属性。
简单来说,除了 postmaster(需要重启)和 internal(编译时确定,不可改)这两种类型的参数外,绝大部分日常运维和调优参数都可以在不重启数据库的情况下修改。
以下是详细的分类、常见参数列表以及如何操作的指南。
1. 核心概念:通过 Context 判断
PostgreSQL 的 pg_settings 视图中包含一个 context 字段,它决定了参数的修改方式。不需要重启的 Context 类型包括:
sighup: 修改配置文件(postgresql.conf)后,发送 SIGHUP 信号(或执行 reload)即可生效。全局生效,通常用于系统级设置。
user: 单个用户可以修改,仅影响当前会话(Session)。
superuser: 仅超级用户可以修改,仅影响当前会话。
backend: 修改配置文件并 reload 后,仅对新建立的连接生效,现有连接不受影响。
2. 常见的不需要重启的参数分类
以下是实际生产环境中,经常需要在运行时动态调整的参数类别:
A. 内存与性能调优 (Session/User 级别)
这些参数通常可以在会话级别调整,也可以全局修改后 reload 生效。
work_mem: 最常用的调优参数。决定排序、哈希表操作可用的内存大小。
maintenance_work_mem: 决定 VACUUM、CREATE INDEX 等维护操作使用的内存。
temp_buffers: 临时表使用的缓冲区大小。
vacuum_cost_limit: 控制自动清理进程的资源消耗上限。
B. 日志与监控 (Sighup 级别)
在排查故障时,我们经常需要动态开启或关闭日志,无需重启。
log_min_duration_statement: 记录执行时间超过多少毫秒的 SQL(慢查询日志)。
log_statement: 控制记录哪些类型的 SQL(如 ddl, mod, all)。
log_destination: 日志输出目标(如 csvlog, stderr)。
log_connections / log_disconnections: 记录连接和断开。
C. 自动清理 (Autovacuum)
调整自动清理策略以应对数据膨胀。
autovacuum_naptime: 自动清理进程的唤醒间隔。
autovacuum_vacuum_scale_factor: 触发 Vacuum 的表大小比例。
autovacuum_analyze_scale_factor: 触发 Analyze 的比例。
D. 超时与安全控制
statement_timeout: 查询执行的最长时间,超时则强制中断。
lock_timeout: 获取锁等待的最长时间。
idle_in_transaction_session_timeout: 事务处于空闲状态的最大时长(防止长事务卡死数据库)。
E. 复制与写入策略
synchronous_commit: 控制事务提交的持久化级别(on, off, local, remote_write 等)。这是一个非常强大的参数,可以在性能和数据安全性之间动态切换。
3. 如何查询哪些参数不需要重启?
你可以直接在数据库中运行 SQL 查询来获取当前版本支持动态修改的所有参数:
SQL
SELECT name, context, setting, unit, short_desc
FROM pg_settings
WHERE context NOT IN ('postmaster', 'internal');
结果解读:
只要不在排除列表中,理论上都可以动态修改。
重点关注 context 为 sighup 和 user 的行。
4. 如何在不重启的情况下修改参数?
有两种主要场景:
场景一:全局修改(永久生效)
如果你想修改配置并让所有进程(或新进程)生效:
修改配置: 使用 ALTER SYSTEM 命令(推荐,它会写入 postgresql.auto.conf)或直接编辑 postgresql.conf。
SQL
-- 示例:将慢查询阈值设置为 1秒
ALTER SYSTEM SET log_min_duration_statement = 1000;
重新加载配置 (Reload):
SQL
SELECT pg_reload_conf();
或者在操作系统层面: pg_ctl reload 或 kill -HUP <主进程PID>。
场景二:仅当前会话修改(临时生效)
如果你只想让当前的 SQL 连接使用特定的配置(例如为了跑一个大报表临时增加内存):
SQL
-- 仅对当前窗口生效,断开连接后失效
SET work_mem = '64MB';
-- 执行你的复杂查询
SELECT ...;
|