Postgrsql 从节点宕机,主节点执行DML语句出现等待情况

来源:这里教程网 时间:2026-03-14 20:07:47 作者:

一、问题描述 postgresql主从集群,当集群中的从节点宕机后,主节点执行DDL与DML时出现语句等待情况。 二、问题原因分析 由于当前PostGresql集群主从节点配置了流复制状态,主从节点采用半同步复制关系, 一旦出现网络抖动或者从节点故障 ,复制关系不会自动降级为异步模式, 导致同步事务进入等待状态。 三、解决方法 针对这个问题需要对同步复制进行降级处理,下面介绍一下如何设置事务可靠性级别。

PostgreSQL 支持在会话中设置事务的可靠性级别。 off 表示commit 时不需要等待wal 持久化。 local 表示commit 是只需要等待本地数据库的wal 持久化。 remote_write 表示commit 需要等待本地数据库的wal 持久化,同时需要等待sync standby节点wal write buffer完成(不需要持久化)。 on 表示commit 需要等待本地数据库的wal 持久化,同时需要等待sync standby节点wal持久化。 提醒一点, synchronous_commit 的任何一种设置,都不影响wal日志持久化必须先于shared buffer脏数据持久化。 所以不管你怎么设置,都不好影响数据的一致性。

synchronous_commit = off                # synchronization level;
                                        # off, local, remote_write, or on

实现同步复制降级

如果 backend process 进入了等待循环,只接受几种信号降级。 并且降级后会告警,表示本地wal已持久化,但是同步从节点不确定wal有没有持久化。如果你只配置了1个从节点,并且将它配置为同步流复制节点。一旦出现网络抖动和从节点故障,将导致同步事务进入等待状态。 方法1. 修改配置文件并重置

$ vi postgresql.conf  
synchronous_commit = local
$ pg_ctl reload

然后cancel 所有query .

postgres=# select pg_cancel_backend(pid) from pg_stat_activity where pid<>pg_backend_pid();

收到这样的信号,表示事务成功提交,同时表示WAL不知道有没有同步到sync standby。

WARNING:  canceling wait for synchronous replication due to user request
DETAIL:  The transaction has already committed locally, but might not have been replicated to the standby.
COMMITpostgres=# show synchronous_commit ;
 synchronous_commit 
--------------------
 off
(1 row)

同时它会读到全局变量synchronous_commit 已经是 local了。 这样就完成了降级的动作。

方法2. 方法1的降级需要对已有的正在等待wal sync的pid使用cancel进行处理,有点不人性化。 可以通过修改代码的方式,做到更人性化。 SyncRepWaitForLSN for循环中,加一个判断,如果发现全局变量sync commit变成local, off了,则告警并退出。这样就不需要人为的去cancel query了.

WARNING:  canceling wait for synchronous replication due to user request
DETAIL:  The transaction has already committed locally, but might not have been replicated to the standby.

相关推荐

热文推荐