逻辑解码是将数据库表的所有持久性更改提取到一种连贯、易于理解的格式中的过程,可以在没有详细了解数据库内部状态的情况下进行解释。
在 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_level
参数更改之前的一些 WAL 记录将不会被解码。
创建逻辑槽需要有关所有当前正在运行的事务的信息。在主服务器上,此信息可以直接获得,但在备用服务器上,必须从主服务器获取此信息。因此,槽创建可能需要等待主服务器上发生一些活动。如果主服务器处于空闲状态,则在备用服务器上创建逻辑槽可能需要相当长的时间。通过在主服务器上调用 pg_log_standby_snapshot
函数,可以加快速度。
复制槽在崩溃后持久存在,并且不知道其消费者的状态。即使没有连接使用它们,它们也会阻止删除必需的资源。这会消耗存储空间,因为只要复制槽需要,VACUUM
就无法删除所需的 WAL 或系统目录中的所需行列。在极端情况下,这可能会导致数据库关闭,以防止事务 ID 回绕(参见 第 24.1.5 节)。因此,如果不再需要槽,则应将其删除。
可以使用 pg_create_logical_replication_slot
的 failover
参数将主服务器上的逻辑复制槽同步到热备用服务器,或者在创建槽时使用 failover
选项 CREATE SUBSCRIPTION
,然后在备用服务器上调用 pg_sync_replication_slots
。通过在备用服务器上设置 sync_replication_slots
,可以在 slotsync worker 中定期同步故障转移槽。为了使同步工作,必须在主服务器和备用服务器之间有一个物理复制槽(即,在备用服务器上应配置 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
选项抑制它。
如果您在文档中发现任何不正确的内容,与您对特定功能的体验不符,或者需要进一步说明,请使用此表格报告文档问题。