逻辑解码是将数据库表中所有持久性更改提取成连贯、易于理解的格式的过程,这种格式无需详细了解数据库的内部状态即可解释。
在 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 节)。因此,如果不再需要某个槽,则应将其删除。
可以使用 pg_create_logical_replication_slot
的 failover
参数,或者在使用 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
选项来抑制它。
如果您在文档中看到任何不正确、与您使用特定功能的经验不符或需要进一步澄清的内容,请使用此表单报告文档问题。