逻辑解码是将数据库表中所有持久化更改提取为一致的、易于理解的格式的过程,该格式可以在无需详细了解数据库内部状态的情况下进行解释。
在 PostgreSQL 中,逻辑解码是通过解码预写日志内容来实现的,该日志描述了存储层上的更改,并将其解码为应用程序特定的形式,例如元组流或 SQL 语句。
在逻辑复制的上下文中,一个插槽表示一条更改流,该流可以按照更改在源服务器上进行的顺序重放给客户端。每个插槽从单个数据库流出一系列更改。
PostgreSQL 也有流复制插槽(参见 第 26.2.5 节),但它们的使用方式略有不同。
复制插槽具有一个标识符,该标识符在 PostgreSQL 群集中的所有数据库中都是唯一的。插槽独立于使用它们的连接而持久存在,并且是防崩溃的。
在正常运行中,逻辑插槽只会发出更改一次。每个插槽的当前位置仅在检查点时持久存在,因此在崩溃的情况下,插槽可能会返回到较早的 LSN,这会导致服务器重启时再次发送最近的更改。逻辑解码客户端负责避免因多次处理同一消息而产生的不良影响。客户端可能希望在解码时记录他们看到的最后一个 LSN,并跳过任何重复的数据或(在使用复制协议时)请求解码从该 LSN 开始,而不是让服务器确定开始点。复制进度跟踪功能专为此目的而设计,请参见 复制源。
一个数据库可以存在多个独立插槽。每个插槽都有其自己的状态,允许不同的使用者从数据库更改流的不同点接收更改。对于大多数应用程序,每个使用者都需要一个单独的插槽。
逻辑复制插槽不知道接收方状态。甚至有可能在不同时间有多个不同的接收方使用同一个插槽;他们将获得从上一个接收方停止消费更改时开始的更改。任何给定时间,只有一个接收方可以从插槽消费更改。
还可以对热备用服务器创建逻辑复制槽。为防止VACUUM
从系统目录中删除所需行,应在备用服务器上设置hot_standby_feedback
。即使如此,如果删除任何所需行,此槽都会作废。强烈建议在主服务器和备用服务器之间使用物理槽。否则,hot_standby_feedback
只能在连接有效期间工作(例如,节点重启将会中断该连接)。然后,主服务器可能删除备用服务器上的逻辑解码可能需要的系统目录行(因为它不知道备用服务器上的catalog_xmin
)。如果主服务器上的wal_level
降至低于logical
,那么备用服务器上的现有逻辑槽也会失效。这是因为备用服务器一检测到 WAL 流中发生这样的变化就会执行此操作。这意味着,对于落后的 Walsender(如果存在),一些 WAL 记录(直至主服务器上的wal_level
参数发生更改)不会被解码。
创建逻辑槽需要有关当前运行的所有事务的信息。在主服务器上,可直接利用此信息,但在备用服务器上,必须从主服务器获取此信息。因此,槽创建可能需要等待主服务器上发生某些活动。如果主服务器空闲,在备用服务器上创建逻辑槽可能需要显著时间。可以在主服务器上调用pg_log_standby_snapshot
函数来加速此过程。
复制槽在崩溃后仍会保留,并且不知道其使用者状态。它们会阻止删除所需资源,即使没有使用这些资源的连接。只要复制槽需要它们,VACUUM
就无法删除所需 WAL 或系统目录中的所需行,所以这会占用存储空间。在极端情况下,这会导致数据库关闭,以防止事务 ID 环绕(参见第 24.1.5 节)。所以,如果不再需要某个槽,则应将其丢弃。
可以利用 failover
参数和 pg_create_logical_replication_slot
在热备用数据库中同步主数据库上的逻辑复制槽,或者利用 CREATE SUBSCRIPTION
在槽创建期间利用 failover
选项,随后在备用数据库中调用 pg_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 之前,主服务器不会完全关闭。
在故障转移后恢复逻辑复制的能力取决于 pg_replication_slots。故障转移时备用服务器上已同步槽的 synced
值。只有在故障转移前备用服务器上的持久槽已达到 true 同步状态后才能用于故障转移后的逻辑复制。临时同步槽无法用于逻辑解码,因此无法恢复这些槽的逻辑复制。例如,如果同步槽由于订阅已禁用而无法在备用服务器上变为持久,则即使在启用订阅后也无法在故障转移后恢复订阅。
若要从已同步的逻辑槽恢复故障转移后的逻辑复制,必须修改订阅的“conninfo”,使其指向新的主服务器。该操作使用 ALTER SUBSCRIPTION ... CONNECTION
来完成。建议在提升备用服务器之前先禁用订阅,并在修改连接字符串后重新启用订阅。
在提升期间,旧主服务器可能会重新启动,如果未禁用订阅,逻辑订阅者可能在提升后仍会从旧主服务器接收数据,直至连接字符串被修改。这可能会导致数据不一致的问题,从而阻止逻辑订阅者继续从新的主服务器进行复制。
输出插件将预写日志的内部表示形式中的数据转换为复制槽使用者的所需格式。
使用流复制接口创建新的复制槽时(参见 CREATE_REPLICATION_SLOT),将导出一个快照(参见 章节 9.28.5),该快照会准确显示所有更改将在更改流中包含的,数据库在此快照之后的状态。可将此快照用于创建新副本,方法是使用 SET TRANSACTION SNAPSHOT
读取槽创建时数据库的状态。然后可使用此事务转储该时间点的数据库状态,然后再使用该槽的内容更新此状态,而不用丢失任何更改。
并非总是可以创建快照。尤其是,连接到热备用时,快照创建将失败。不需要导出快照的应用程序可使用 NOEXPORT_SNAPSHOT
选项将其禁止。