找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1788

积分

0

好友

241

主题
发表于 2025-12-25 12:13:12 | 查看: 32| 回复: 0

PostgreSQL 17 引入了逻辑复制槽故障转移功能,该功能的核心价值在于:当主库发生故障且备库被提升为新主库时,无需重新创建逻辑复制槽即可安全、不丢失数据地接管原有的逻辑复制流,从而极大提升了基于逻辑复制的数据库高可用架构的可靠性。

关键配置参数

实现复制槽同步功能涉及以下三个关键配置参数:

参数名 生效位置 说明
hot_standby_feedback 备库 必须开启,用于通知主库保留备库可能需要的旧数据版本。
sync_replication_slots 备库 控制是否启动后台进程自动同步复制槽信息。
synchronized_standby_slots 主库 指定一组物理复制槽名,确保数据先同步到物理备库,再发送给逻辑下游,保障故障切换后的数据一致性。

功能演示:手动同步逻辑复制槽

下面通过一个完整示例演示逻辑复制槽同步的手动操作流程。

环境准备

  1. 主库A: 设置 wal_level=logical
  2. 备库B: 设置 hot_standby_feedback=on,并通过 primary_slot_name='standby1' 连接主库。
  3. 逻辑下游C: 用于订阅逻辑复制数据。

步骤一:在主库创建逻辑复制槽

在主库A执行以下命令,注意最后一个参数需设置为 true,这表示该槽需要被同步到备库。

postgres=# select pg_create_logical_replication_slot('pub_slotname1', 'pgoutput', false, false, true);
       pg_create_logical_replication_slot
-------------------------------------------
 (pub_slotname1,0/5000098)
(1 row)

步骤二:在备库手动触发同步

首先,在备库B查看当前复制槽状态(此时应为空):

postgres=# select * from pg_replication_slots;
 slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn | wal_status | safe_wal_size | two_phase | two_phase_at | inactive_since | conflicting | invalidation_reason | failover | synced
-----------+--------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------+------------+---------------+-----------+--------------+----------------+-------------+---------------------+----------+--------
(0 rows)

然后,执行手动同步命令:

postgres=# select pg_sync_replication_slots();
 pg_sync_replication_slots
---------------------------
 (1 row)

再次查看,确认主库的 pub_slotname1 槽已同步到备库:

postgres=# select slot_name,restart_lsn,confirmed_flush_lsn from pg_replication_slots;
   slot_name   | restart_lsn | confirmed_flush_lsn
---------------+-------------+---------------------
 pub_slotname1 | 0/5000060   | 0/5000098
(1 row)

步骤三:配置逻辑发布与订阅

在主库A创建发布:

CREATE PUBLICATION all_tables_pub FOR ALL TABLES;

在逻辑下游C创建订阅,并指定使用已存在的复制槽 pub_slotname1

postgres=# CREATE SUBSCRIPTION sub_to_main
CONNECTION 'host=localhost port=10080 dbname=postgres user=lchch password=secret'
PUBLICATION all_tables_pub
WITH (slot_name = 'pub_slotname1', create_slot = false);
CREATE SUBSCRIPTION

步骤四:验证数据同步与槽位点更新

在主库A插入测试数据,并观察复制槽位点推进:

postgres=# insert into t1 values(100,1,'aa');
INSERT 0 1
postgres=# select slot_name,restart_lsn,confirmed_flush_lsn,active from pg_replication_slots ;
   slot_name   | restart_lsn | confirmed_flush_lsn | active
---------------+-------------+---------------------+--------
 pub_slotname1 | 0/5000D58   | 0/5000D90           | t
 standby1      | 0/5000D90   |                     | t
(2 rows)

此时,备库B上的同步槽位点尚未更新:

postgres=# select slot_name,restart_lsn,confirmed_flush_lsn,active from pg_replication_slots ;
   slot_name   | restart_lsn | confirmed_flush_lsn | active
---------------+-------------+---------------------+--------
 pub_slotname1 | 0/5000060   | 0/5000098           | f
(1 row)

在备库B再次执行手动同步,可见槽的 confirmed_flush_lsn 已更新至与主库一致:

postgres=# select pg_sync_replication_slots();
 pg_sync_replication_slots
---------------------------
 (1 row)

postgres=# select slot_name,restart_lsn,confirmed_flush_lsn,active from pg_replication_slots ;
   slot_name   | restart_lsn | confirmed_flush_lsn | active
---------------+-------------+---------------------+--------
 pub_slotname1 | 0/5000BD0   | 0/5000D90           | f
(1 row)

至此,演示完成。此时若主库A宕机,VIP漂移至备库B并使B库升主,逻辑下游C即可无缝、无数据丢失地继续从新主库进行逻辑复制,实现了平滑的主备切换。

内核逻辑深度解读

上述演示使用了手动同步命令,若开启 sync_replication_slots 参数,Postmaster会启动一个后台进程,循环检查并自动同步复制槽。该进程的等待时间会根据复制活动动态调整(从200ms到30s),以平衡及时性和系统开销。

实现此功能的核心机制与限制如下:

  1. 依赖 hot_standby_feedback: 备库必须开启此参数。其主要目的是保护备库上可能已被逻辑解码事务引用的catalog(系统表)数据不被过早清理。这样,故障转移后,新主库仍有完整的元数据支持逻辑解码。但这可能加剧主库因无法及时清理死元组而产生的表膨胀问题。

  2. 同步的发起与内容: 同步操作由备库主动发起。备库连接主库,查询主库上所有标记为可同步的复制槽信息,并据此在本地创建或更新对应的“同步复制槽”。同步的不仅是LSN位点,更关键的是维护解码所需的一致性快照信息。因此,在开启此功能后,备库至少需要额外读取一次WAL日志来维护快照,这对备库性能有一定影响。

  3. 处理WAL缺口问题: 在备库创建同步槽时,若该槽所需的最早WAL日志已在备库被删除,则会创建一个“非法”的槽,并为其设置一个非常大的LSN(InvalidXLogRecPtr)。在后续同步更新槽位点时,也可能因维护快照失败而将槽位点设置为一个超大值。这会导致备库同步槽的LSN反而大于主库原槽的LSN

  4. 同步等待机制: 针对上述“备库槽位点超前”的特殊情况,最新的内核补丁增加了等待逻辑。当手动执行 pg_sync_replication_slots() 遇到此情况时,函数会阻塞,直到主库上对应逻辑复制槽的消费位点(confirmed_flush_lsn)追平或超过备库上同步槽的超前位点后,才返回成功。这确保了同步操作的最终正确性。

总结与展望

PostgreSQL 17的逻辑复制槽同步功能,为解决逻辑复制下的高可用问题迈出了关键一步。其设计在追求正确性的过程中,不可避免地引入了对主库膨胀的潜在影响(hot_standby_feedback)以及备库额外的性能开销(多次读取WAL)。这反映了在构建健壮的数据库高可用方案时,往往需要在特性、性能与复杂度之间进行权衡。当前实现已解决了核心的数据一致性问题,相信未来版本会在此基础上持续优化,寻求更优的平衡点。

逻辑复制槽同步示意图




上一篇:从输入URL到页面展示完整流程解析:2025面试高频考点与性能优化策略
下一篇:嵌入式Bootloader安全机制设计:基于STM32的镜像校验、签名认证与内存保护
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-10 18:32 , Processed in 0.282282 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表