PostgreSQL的同步复制槽功能,其核心目标是保障在使用物理流复制的高可用架构中,当发生主备切换(Failover)时,逻辑复制的消费者能够无缝迁移到新提升的主库,且不丢失任何已消费的数据。
这一机制的前提是:对于任何一个同步复制槽,其消费者在原主库上已消费的最后WAL日志位置(LSN)之前的所有WAL,都必须已经同步到物理备库。PostgreSQL 19引入的 pg_sync_replication_slots() 函数就如同设置了一道栅栏。当在备库执行此函数时,它会等待,直到函数被调用前主库上存在的所有同步复制槽(若有多个,则取消费进度最慢的那个WAL位置)对应的WAL数据,都已同步到当前备库,函数才会返回true。
然而,这个机制存在一个根本性的异步问题:备库所感知的永远是主库过去某个时刻的槽状态。当消费者在主库持续消费时,备库看到的WAL位置永远比实际情况更“旧”。因此,补丁提供的保证并非“切换后不丢WAL”,而是“切换后不删除消费者可能需要的WAL”。其设计哲学是:宁可让消费者在新主库上重复消费(要求消费逻辑实现幂等),也绝不能因WAL被过早清理而导致数据丢失。
真正保证WAL不丢失的,是PostgreSQL早已存在的基于法定人数的同步流复制(quorum-based sync replication)。但这个机制本身也有一个细微的漏洞:当同步复制因网络等问题被阻塞时,它只会阻止事务的COMMIT命令向客户端返回成功,却不会阻止该事务的WAL在本地持久化。结果是,客户端认为事务未提交,但实际上WAL已经生成,主库上的逻辑复制消费者已经可以读取并消费这个事务的变更。此时,逻辑消费者可能比物理备库“知道”得更多。pg_sync_replication_slots() 函数在此场景下也有作用,它可以将槽标记为“未同步”状态。
PostgreSQL同步复制槽的核心挑战在于可能引发的阻塞,而非数据丢失。
启用同步复制槽功能配置较为复杂,其必要条件包括:
- 必须存在一个配置了
primary_slot_name的物理备库(Hot Standby)。
- 必须将该物理备库使用的物理复制槽名称,配置到主库的
synchronized_standby_slots 参数中。
- 该物理备库必须开启
hot_standby_feedback = on(注意其可能引发的表膨胀与 vacuum 效率问题副作用)。
- 主库在关闭时,会等待
synchronized_standby_slots 中列出的物理备库确认已接收到主库最后刷新的WAL位置。
在PostgreSQL 18中,这套机制实质上是用可用性来换取切换后逻辑复制的可靠性。因为一旦配置,逻辑复制的进度将被绑定的物理备库的同步进度所制约。
同步逻辑复制槽配置详解
核心配置参数
前置条件验证
根据代码,同步功能生效必须满足:
wal_level >= logical
- 备库配置了
primary_slot_name
- 备库
hot_standby_feedback = on
- 备库配置了有效的
primary_conninfo
配置示例
主库配置:
-- 创建物理复制槽
SELECT pg_create_physical_replication_slot(‘standby_slot’);
-- 创建支持故障转移的逻辑复制槽
SELECT pg_create_logical_replication_slot(‘logical_slot’, ‘pgoutput’, false, false, true);
-- 配置同步槽
ALTER SYSTEM SET synchronized_standby_slots = ‘standby_slot’;
SELECT pg_reload_conf();
备库配置 (postgresql.conf):
primary_conninfo = ‘host=primary_host port=5432 user=replicator’
primary_slot_name = ‘standby_slot’
hot_standby_feedback = on
sync_replication_slots = on
同步机制与潜在阻塞点
当 synchronized_standby_slots 配置了多个物理复制槽时,逻辑复制槽需要等待列表中所有槽对应的备库都同步到指定WAL位置,而不是其中任意一个。这是通过遍历所有配置的槽并检查其 restart_lsn 来实现的,只有全部满足条件,等待才会解除。
这意味着:如果列表中任何一个物理备库出现延迟、网络中断或失效,所有依赖于此的逻辑复制进程都将被阻塞。 这种“等待所有”的策略虽然最大限度地保障了数据一致性,但显著牺牲了系统的可用性与吞吐量。一个自然的疑问是:为何不采用类似同步流复制中基于“法定人数(Quorum)”的机制,只需多数备库同步即可,从而在可靠性与可用性间取得更好平衡呢?
这正是当前PostgreSQL同步复制槽方案在构建高可用架构时的一个关键权衡点,也是设计者和使用者都需要深思的。在采用此方案前,务必充分评估其阻塞风险,并进行完整的故障转移测试,以确保它符合你的业务连续性要求。
|