synchronous_commit=on单独设置仍可能丢数据,因其仅在synchronous_standby_names非空时才触发等待备库确认;若该参数为空(默认),on退化为local,仅等待本地落盘而不同步备库。

synchronous_commit 配置对丢数据有决定性影响,但单靠它不够——必须和 synchronous_standby_names 配合才真正起作用。
为什么只设 synchronous_commit=on 还是可能丢数据
很多人以为把 synchronous_commit 设成 on 就万事大吉,结果主库一挂,发现备库没收到最新 WAL。这是因为:
-
synchronous_commit=on本身只表示“等待同步备库确认接收并持久化 WAL”,但它不指定哪个备库是同步的——synchronous_standby_names才是开关 - 如果
synchronous_standby_names是空的(默认值),哪怕synchronous_commit=on,实际行为也等同于local:只等本地落盘,不等任何备库 - 备库没配置
application_name,或名字和synchronous_standby_names不匹配,也会被忽略,降级为异步
synchronous_commit 各值在同步场景下的真实含义
重点看带复制的场景(即 synchronous_standby_names 已设置):
-
remote_write:主库等备库把 WAL 写进 OS 缓存就返回。大多数生产环境够用,性能损失小;但极端情况下(主库磁盘坏 + 备库刚宕机),可能丢最后几毫秒事务 -
on:主库等备库把 WAL 持久化到磁盘(fsync)才返回。RPO=0 的基础保障,推荐核心业务使用 -
remote_apply:主库等备库不仅写盘,还把 WAL 应用到数据页才返回。延迟最高,适合跨机房容灾,但要注意备库 apply 能力瓶颈 -
local和off:完全不等备库,即使synchronous_standby_names有值也无效
必须配对的三个动作
只改一个参数不会生效,这三步缺一不可:
- 主库
postgresql.conf中同时设置:synchronous_commit = on和synchronous_standby_names = 'FIRST 1 (s1,s2)'(注意空格和括号格式) - 从库
recovery.conf(或 12+ 的standby.signal+primary_conninfo)里,primary_conninfo必须包含application_name=s1(名字要和上面列表中一致) - 主库
pg_hba.conf开放 replication 权限,且用户已执行ALTER USER replica REPLICATION
容易被忽略的故障点
同步看似开了,但查 pg_stat_replication 发现 sync_state 是 async?常见原因:
- 从库启动后没连上主库(网络不通、端口被拦、
primary_conninfo里 host/port/user/password 错) -
application_name大小写不一致,比如主库写s1,从库写S1,PostgreSQL 严格区分 - 主库
wal_level不是replica或更高(minimal会直接拒绝同步连接) - 备库 WAL 接收进程卡住,查
pg_stat_wal_receiver看status是否为streaming
真正防丢数据的关键不在参数名有多“同步”,而在主从之间那条 WAL 流是否稳定建立、命名是否对得上、落盘是否真完成——这些细节松动一点,RPO 就从 0 变成不确定。

















