# 参数作用域与变更方式

LLMS 索引： [llms.txt](/llms.txt)

---

一个参数变更有三个不同状态：

```text
desired
  inventory/template/DCS/database-role policy 想要什么

configured
  file/catalog/command line 中写了什么

effective
  当前 server/session 实际用了什么
```

它们可以不同。

最常见事故不是参数值本身，而是：

- 改错 scope；
- 被更高优先级覆盖；
- reload 了一个必须 restart 的参数；
- 只改 primary，failover 后消失；
- 手工 `ALTER SYSTEM` 被下一次 IaC 覆盖；
- 改了 role default，却继续复用旧 pool session；
- `pending_restart` 长期无人处理。

## 27.5.1 编译、初始化、启动、reload 与会话级 {#item-27-5-1}

### 先问“这个属性什么时候还能改变”

从最早到最晚：

```text
build/compile
  -> initdb
      -> postmaster startup
          -> SIGHUP reload
              -> backend startup
                  -> superuser/session
                      -> transaction
```

越靠左，变更成本、兼容性和回退风险通常越大。

### build-time

有些物理属性来自 build：

```text
block size
some segment/page layout options
compiled features/libraries
architecture/compiler
```

查询：

```sql
SHOW block_size;
SELECT version();
```

这些不是普通 GUC。改变 block size 通常意味着不同 binary/cluster physical format，
不能用 reload/restart 改现有集群。

### initdb-time

cluster 创建时固定或高度绑定：

```text
encoding
locale/ICU provider and version choices
data checksums
WAL segment size
system identifier
```

例如：

```sql
SHOW data_checksums;
SHOW wal_segment_size;
SELECT datname, encoding, datcollate, datctype
FROM pg_database;
```

某些能力可能有离线工具/特定版本转换路径，但不能把它当作普通 GUC rollout。
参数 ADR 要标注：

```text
new cluster / migration / offline conversion
```

而不是写“restart”。

### `pg_settings.context`

```sql
SELECT DISTINCT context
FROM pg_settings
ORDER BY context;
```

典型语义：

| context | 最早/最小变化边界 |
|---|---|
| `internal` | 不能由用户改变，来自 build/init/internal |
| `postmaster` | server start |
| `sighup` | config reload |
| `superuser-backend` | backend start，需 superuser/SET privilege |
| `backend` | backend start |
| `superuser` | session 可改，但权限受限 |
| `user` | ordinary session 可改 |

`context=user` 只表示权限/生命周期允许，不表示业务上可随意改。

### restart parameter

```text
shared_buffers
max_connections
max_worker_processes
shared_preload_libraries
huge_pages
```

写进 config 后 reload：

```sql
SELECT name, setting, pending_restart
FROM pg_settings
WHERE pending_restart;
```

`pending_restart=true` 表示 file 中的新值尚未成为 effective value。不能把 config diff
当作运行事实。

### reload parameter

SIGHUP：

```sql
SELECT pg_reload_conf();
```

或平台命令。reload：

- 重新读取配置；
- 不停止 server；
- 不保证每个参数/每个 backend 立即按你想象生效；
- 不证明配置无 syntax/semantic error；
- 不处理 postmaster parameter。

先查 `pg_file_settings.error`，再 reload，随后查 effective/source。

### backend-start parameter

一些设置只在新 backend 建立时取得。reload 后：

```text
new sessions see candidate
old sessions retain previous
```

connection pool 可让“旧 session”存活很久。变更计划要包括：

- pool recycle/drain；
- prepared/session state；
- transaction 不中断；
- 新旧 session 混合窗口；
- verification 分别取样。

### session 与 transaction

```sql
SHOW work_mem;

SET work_mem = '32MB';
-- 当前 session 后续 statement 使用

BEGIN;
SET LOCAL work_mem = '128MB';
-- 仅当前 transaction
COMMIT;
-- 回到 session value

RESET work_mem;
-- 回到 session default
```

`SET LOCAL` 在 transaction 外没有你想要的持久语义。transaction rollback 也影响配置
变化；用 connection pool 时必须测试 reset 行为。

### 查单位与规范化值

`pg_settings.setting` 常是 base unit：

```sql
SELECT
    name,
    setting,
    unit,
    vartype,
    min_val,
    max_val,
    enumvals
FROM pg_settings
WHERE name IN ('work_mem', 'shared_buffers', 'checkpoint_timeout');
```

不要把：

```text
shared_buffers setting=62592
```

读成 bytes；unit 是 `8kB`。

## 27.5.2 系统、数据库、角色与事务覆盖层 {#item-27-5-2}

### global 配置层

来源可能包括：

```text
compiled boot value
postgresql.conf + includes
postgresql.auto.conf / ALTER SYSTEM
postmaster command-line -c
environment/client startup
```

`postgresql.auto.conf` 在普通 config 后读取；server command-line setting 又可覆盖 file。
参考沙箱：

```text
max_connections = 500
source          = command line
```

所以在 `postgresql.conf` 写 200、reload/restart 后，若 Patroni/postmaster 仍用
`-c max_connections=500`，effective 仍可能是 500。

### database/role defaults

```sql
ALTER DATABASE app
SET statement_timeout = '5s';

ALTER ROLE dbuser_app
SET work_mem = '16MB';

ALTER ROLE dbuser_app
IN DATABASE app
SET statement_timeout = '2s';
```

新 login 的优先关系可概括为：

```text
global
  < database-specific
  < role-specific
  < role-in-database-specific
  < session SET / startup option
  < transaction SET LOCAL
```

database 与 role 的精确冲突规则：role-in-database 最具体；role-specific 覆盖
database-specific。

官方
[`Setting Parameters`](https://www.postgresql.org/docs/18/config-setting.html)
强调 `ALTER DATABASE`/`ALTER ROLE` 只在**新 session**建立时应用。`SET ROLE` 不会重新
加载目标 role 的配置 default。

### catalog 事实

这些 default 存在：

```sql
SELECT
    setdatabase::regdatabase,
    setrole::regrole,
    setconfig
FROM pg_db_role_setting
ORDER BY setdatabase, setrole;
```

需要处理 OID=0 的 all database/all role 显示；不要直接把系统 catalog 结果发给不该
看到 role policy 的用户。

### current session 的 source

```sql
SELECT
    name,
    setting,
    unit,
    source,
    sourcefile,
    sourceline,
    reset_val,
    boot_val
FROM pg_settings
WHERE name = 'statement_timeout';
```

`sourcefile` 只对有 `pg_read_all_settings` 等权限的用户可见。公共报告不应发布主机
绝对路径。

注意：

```text
source
```

在当前 session 被 `SET` 后会显示 session source；要验证 cluster default，需要新建
干净 session 或查 catalog/file，不要在已被测试脚本修改的 session 中判断。

### `ALTER SYSTEM`

```sql
ALTER SYSTEM SET work_mem = '64MB';
SELECT pg_reload_conf();
```

写入 `postgresql.auto.conf`。它适合某些 standalone 管理模式，但在 IaC/Patroni/Pigsty
中会产生第二个 desired-state writer。

Pigsty 官方
[parameter scopes](https://pigsty.io/docs/pgsql/config/param/)
指出，受管集群的 `postgresql.auto.conf` 可由 `pg_parameters` 管理，手工
`ALTER SYSTEM` 可能被下一次 playbook 覆盖。生产持久变更应回到 inventory/desired
state，除非有明确 break-glass 流程和回写。

### `ALTER SYSTEM RESET ALL` 很危险

它不是“恢复 PostgreSQL 默认”，而是清空 `postgresql.auto.conf` 中 ALTER SYSTEM
设置；文件可能还有平台管理内容。不要为了撤一项变更执行 RESET ALL。

精确回退：

```sql
ALTER SYSTEM RESET work_mem;
```

仍要确认 lower-priority value 是预期值。

### startup packet / `PGOPTIONS`

libpq：

```bash
env PGOPTIONS="-c statement_timeout=2s -c plan_cache_mode=auto" \
  psql ...
```

只影响连接 session。第 27 章实验用它确保 candidate 不落盘。

风险：

- application 可覆盖平台 default；
- pool 连接建立时固定；
- 不允许的 GUC 会导致连接失败；
- connection string/log/env 可能泄露；
- startup setting provenance 易被忽略。

应用允许的 startup option 应纳入 policy。

### 自定义 GUC 与 extension

extension 可能增加：

```text
shared_preload_libraries
extension.parameter
custom namespace
```

参数在 extension 未加载/版本变化时可能无效或阻止启动。升级前检查：

```text
available extension version
preload library presence
pg_file_settings errors
standby binary parity
rollback binary compatibility
```

## 27.5.3 配置漂移、审计、回退和滚动风险 {#item-27-5-3}

### 一条事实查询

```sql
SELECT
    name,
    setting,
    unit,
    context,
    source,
    sourcefile,
    sourceline,
    pending_restart
FROM pg_settings
ORDER BY name;
```

它回答 effective/session fact。配置文件事实：

```sql
SELECT
    sourcefile,
    sourceline,
    seqno,
    name,
    setting,
    applied,
    error
FROM pg_file_settings
ORDER BY seqno;
```

官方
[`pg_file_settings`](https://www.postgresql.org/docs/18/view-pg-file-settings.html)
指出：

- 每条 file entry 一行；
- invalid/syntax error 出现在 `error`；
- 被后续同名项覆盖时 `applied=false`，不一定是 error；
- 它反映**当前文件内容**，不是 last-applied runtime。

两张 view 要一起看。

### duplicate setting

```text
postgresql.conf:100  work_mem=4MB
included/app.conf:20 work_mem=16MB
postgresql.auto.conf work_mem=64MB
command line         none
```

只 grep 第一处会误判。用 `seqno/applied/source` 还原 precedence。

### drift 类型

| drift | desired | configured | effective |
|---|---|---|---|
| 未应用 | new | new | old |
| 手工热改 | old | manual new | manual new |
| command override | desired | desired | command |
| session override | desired | desired | session |
| member mismatch | same | differs by node | differs |
| pool stale | new | new | old/new sessions |
| invalid file | new | error | old |

每种 remediation 不同。

### 配置 snapshot 不要泄密

`pg_settings` 里可能有：

- file path；
- library/path；
- connection-like extension setting；
- topology；
- logging destination。

私密 evidence 保存完整；公共报告使用 allowlist：

```text
name
normalized setting
unit
context
coarse source
pending_restart
```

不发布 sourcefile absolute path、secret 或 raw extension config。

### 变更前检查

```text
target cluster/member/role
current desired commit
current effective values on every member
file errors
pending_restart
HA health/lag
backup/recovery health
resource headroom
active DDL/maintenance
pool/session lifecycle
rollback value and command
```

参数名相同不代表 primary/replica 应完全相同，例如 delayed replica；但差异必须是
desired，而不是 drift。

### reload 风险

reload 低于 restart，不等于零风险：

- logging 参数可制造 I/O storm；
- autovacuum 参数可启动更多工作；
- timeout 可中断新 workload；
- HBA/SSL/config error 可影响连接；
- query cost 可在新 planning 时改变 plan；
- backend-start setting 造成混合。

reload 后观察：

```text
config log
pg_settings effective/source
new and old session sample
query/latency/resource
HA/replica/archive
```

### rolling restart 风险

restart parameter 在 HA cluster 中通常逐 member：

```text
replica 1
  -> restart
  -> recover/catch up/validate
replica 2
  -> ...
planned switchover if needed
old primary
```

但是否安全取决于 parameter：

- standby `max_connections` 不应低于 primary，否则 recovery query 限制；
- `max_worker_processes` standby 需要与 primary 相容；
- `shared_preload_libraries` 的 extension/binary 每台都要存在；
- protocol/physical compatibility；
- restart 期间 N+1 capacity；
- failover 在 mixed-version/mixed-config 窗口的行为。

不能一概写“滚动无中断”。

### rollback 也可能 restart

若 candidate 是 postmaster：

```text
apply candidate -> rolling restart
regression -> restore desired -> another rolling restart
```

这段时间风险是两倍操作，不是一条 `git revert`。change window 必须预留 rollback
时长和 N+1 capacity。

### failover 中的 source of truth

Patroni 管理的参数可能来自 DCS/postmaster command line。只编辑 local
`postgresql.conf`：

- Patroni 可能重写；
- failover 后 candidate 消失；
- replica effective 不同；
- automation reconcile 回旧值。

变更前先确定：

```text
who owns this parameter?
template, inventory, DCS, auto.conf, role catalog, or application?
```

一个参数只能有一个持续 desired-state owner。

### configuration ADR

```yaml
parameter: ...
owner: ...
current:
  desired: ...
  configured: ...
  effective: ...
  source: ...
context: postmaster|sighup|user|...
scope: cluster|instance|database|role|session
hypothesis: ...
members:
  - name: ...
    before: ...
apply:
  method: ...
  order: ...
  observation: ...
rollback:
  method: ...
  order: ...
  maximum_time: ...
failure:
  mixed_state_behavior: ...
  failover_behavior: ...
validation:
  native_sql: ...
  file_fact: ...
  Pigsty: ...
```

参数值只是 ADR 中一行；scope、owner、effective evidence 与 mixed-state behavior
同样重要。

---

[上一节：规划器、并行与连接参数](../04/) · [返回本章目录](../) · [下一节：模板参数与集群变更](../06/) ·
[查看全书目录](/toc/) · [查看索引中心](/indexes/)
