9.3 9.4 9.5 9.6 10 11 12 13 14 15 16 17 Current(18)
PostgreSQL中文社区 问题报告 纠错本页面

47.2. 逻辑解码概念 #

47.2.1. 逻辑解码
47.2.2. 复制槽
47.2.3. 复制槽同步
47.2.4. 输出插件
47.2.5. 导出快照

47.2.1. 逻辑解码 #

逻辑解码是一种将对数据库表的所有持久更改抽取到一种清晰、易于理解的格式 的处理,这种技术允许在不了解数据库内部状态的详细知识的前提下解释该格式。

PostgreSQL中,逻辑解码通过解码 预写式日志的内容来实现,预写式日志描述了存储 层面上的更改,而逻辑解码则会把更改解码成一种应用相关的形式,例如一个元组 流或者 SQL 语句流。

47.2.2. 复制槽 #

在逻辑复制的环境下,一个槽表示一个更改流,这些更改可以在客户端上以它们在原服务器上产生的顺序被重播。每一个槽从一个单一数据库中流式传送更改序列。

注意

PostgreSQL也有流复制槽(见第 26.2.5 节),但是它们的使用有所不同。

一个复制槽在一个PostgreSQL集簇的所有数据库之间具有一个唯一的标识符。槽在使用它们的连接之间保持独立并且对于崩溃是安全的。

逻辑槽在正常操作中每次只会发出一次更改。 每个槽的当前位置信息仅在检查点时持久化,因此在 崩溃的情况下,槽可能会返回到较早的 LSN,这将 导致服务器重启时再次发送最近的更改。 逻辑解码客户端负责避免处理同一消息多次带来的不良影响。 客户端可能希望记录它们在解码时看到的最后 LSN,并跳过任何重复的数据,或者 (在使用复制协议时)请求从该 LSN 开始解码,而不是让服务器确定起始点。 复制进度跟踪功能就是为此目的而设计的, 详见 复制来源

对于同一个数据库可能会存在多个独立的槽。每个槽有 自己的状态,允许不同的消费者从该数据库的更改流中的不同点开始接收更改。对于大多数应用, 每个消费者都将要求一个单独的槽。

逻辑复制槽完全不知道接收者的状态。甚至可能会有多个不同的接收者在不同 时间使用同一个槽,它们将只是从上一个接收者停止消费更改的地方开始得到 更改。但在任一给定时刻,只有一个接收者可以从一个槽中消费更改。

逻辑复制槽也可以在热备机上创建。为了防止VACUUM从系统目录中删除所需的行, 应该在备机上设置hot_standby_feedback。尽管如此,如果任何所需的行被删除, 该槽将失效。强烈建议在主机和备机之间使用物理槽。否则,hot_standby_feedback 只在连接存活期间有效(例如节点重启会导致其失效)。然后,主机可能会删除备机逻辑解码 可能需要的系统目录行(因为它不知道备机上的catalog_xmin)。 如果主机上的wal_level降低到低于logical,备机上的现有逻辑槽 也会失效。备机在检测到WAL流中的此类变化后会立即执行此操作。这意味着,对于滞后的walsender(如果有), 主机上wal_level参数变化之前的一些WAL记录将不会被解码。

创建逻辑槽需要有关所有当前运行事务的信息。在主服务器上,这些信息可以直接 获取,但在备用服务器上,这些信息必须从主服务器获取。因此,槽的创建可能需要 等待主服务器上发生一些活动。如果主服务器处于空闲状态,在备用服务器上创建逻辑槽可能会花费显著的时间。 可以通过在主服务器上调用pg_log_standby_snapshot函数来加速这一过程。

小心

复制槽可以在崩溃时保持,并且不知道其消费者的状态。即便没有连接使用它们, 它们也将阻止移除所需的资源。这会消耗存储,因为只要还有一个复制槽需要, WAL 和来自于系统目录的行就不能被VACUUM移除。在极端情况下这会导致数据库关闭以防止事务ID回卷(见第 24.1.5 节)。因此如果不再需要一个槽,那就应该删除它。

47.2.3. 复制槽同步 #

主节点上的逻辑复制槽可以通过使用 failover 参数的 pg_create_logical_replication_slot,或者通过 在创建槽时使用 failover 选项的 CREATE SUBSCRIPTION 来进行同步。 此外,必须在备用节点上启用 sync_replication_slots。 通过在备用节点上启用 sync_replication_slots,故障转移槽可以在 slotsync 工作线程中定期同步。为了使同步工作,主节点和备用节点之间 必须有一个物理复制槽(即, primary_slot_name 应在备用节点上配置),并且 hot_standby_feedback 必须在备用节点上启用。还必须在 primary_conninfo 中指定有效的 dbname。 强烈建议在主节点的 synchronized_standby_slots 列表中命名上述物理复制槽,以防止订阅者消耗更改 的速度超过热备用。即使配置正确,由于等待 synchronized_standby_slots 中命名的槽,向逻辑订阅者发送更改时也会预期一些延迟。 当使用 synchronized_standby_slots 时, 主服务器不会完全关闭,直到与 synchronized_standby_slots 中指定的物理复制槽相关的 备用节点确认接收到 WAL,直到主服务器上最新的刷新位置。

注意

启用 sync_replication_slots 允许自动 定期同步故障转移槽,但也可以使用 pg_sync_replication_slots 函数在备用节点上手动 进行同步。 然而,此函数主要用于测试和调试,使用时应谨慎。 与自动同步不同,它不包括循环重试,使其更容易出现同步失败, 特别是在初始同步场景中,所需的 WAL 文件 或槽的目录行可能已经被删除或面临被删除的风险。 相比之下,通过 sync_replication_slots 的自动同步 提供了持续的槽更新,支持无缝故障转移和高可用性。 因此,这是同步槽的推荐方法。

当槽同步配置如推荐的那样,并且初始同步是通过 pg_sync_replication_slots 自动或手动执行时, 备用节点只能在满足以下条件时持久化同步槽: 主节点上的逻辑复制槽必须保留仍在备用节点上可用的 WAL 和系统 目录行。这确保了数据完整性,并允许逻辑复制在提升后顺利继续。 如果所需的 WAL 或目录行已经从备用节点中清除, 为了避免数据丢失,槽将不会被持久化。在这种情况下,可能会出现以下日志消息:

LOG:  无法同步复制槽 "failover_slot"
DETAIL:  同步可能导致数据丢失,因为远程槽需要 LSN 0/3003F28 的 WAL 和目录 xmin 754,但备用节点的 LSN 为 0/3003F28,目录 xmin 为 756。

如果逻辑复制槽被消费者积极使用,则无需手动干预; 槽将自动推进,并且同步将在下一个周期恢复。 然而,如果没有配置消费者,建议使用 pg_logical_slot_get_changes pg_logical_slot_get_binary_changes 在主节点上手动推进槽,以允许同步继续进行。

故障切换后恢复逻辑复制的能力取决于备用节点故障切换时 pg_replication_slots.synced 值。只有在故障切换前已在备用节点上达到 synced 状态为 true 的持久槽 才能在故障切换后用于逻辑复制。临时 synced 槽不能用于逻辑解码,因此 这些槽的逻辑复制无法恢复。例如,如果由于订阅被禁用, 同步槽无法在备用节点上变为持久槽,则即使启用该订阅, 故障切换后也无法恢复该订阅。

要在从同步逻辑槽故障转移后恢复逻辑复制,必须修改订阅的 'conninfo' 以指向新的主服务器。 这是通过 ALTER SUBSCRIPTION ... CONNECTION 来完成的。建议在提升备用服务器之前先禁用订阅,并在修改连接字符串后重新启用订阅。

小心

在提升期间,旧的主服务器可能会重新启动,如果未禁用订阅,逻辑订阅者可能 会继续从旧的主服务器接收数据,直到连接字符串被更改。这可能导致数据不 一致问题,阻止逻辑订阅者能够继续从新的主服务器进行复制。

47.2.4. 输出插件 #

输出插件将数据从预写式日志的内部表示转换成复制槽的消费者所需的格式。

47.2.5. 导出快照 #

当使用流复制接口创建一个新的复制槽时(参见CREATE_REPLICATION_SLOT), 会导出一个快照(参见第 9.28.5 节), 这将准确显示数据库在创建槽之后的状态,之后所有更改都将包含在更改流中。 这可以用来通过使用SET TRANSACTION SNAPSHOT 来读取创建槽时数据库的状态,从而创建一个新的副本。 然后可以使用该事务来转储数据库在那个时间点的状态,之后可以使用槽的内容更新而不会丢失任何更改。

不需要快照导出的应用程序可以使用 SNAPSHOT 'nothing' 选项来抑制快照导出。