49.2. 逻辑解码概念#
49.2.1. 逻辑解码#
逻辑解码是将数据库表中的所有持久性更改提取到连贯、易于理解的格式中的过程,该格式可以在不详细了解数据库内部状态的情况下进行解释。
在PostgreSQL中,逻辑解码是通过解码预写式日志的内容来实现的,该日志描述了存储级别的更改,并将其转换为特定于应用程序的形式,例如元组流或 SQL 语句。
49.2.2. 复制槽#
在逻辑复制的上下文中,槽表示可以按在源服务器上进行的顺序重放给客户端的更改流。每个槽从单个数据库流式传输一系列更改。
注意
PostgreSQL也有流复制槽(请参阅第 27.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 环绕(请参阅第 25.1.5 节)。因此,如果不再需要某个槽,则应将其删除。
49.2.3. 输出插件#
输出插件将预写日志的内部表示中的数据转换为复制槽使用者所需格式。
49.2.4. 导出的快照#
使用流复制接口(参见CREATE_REPLICATION_SLOT)创建新的复制槽时,将导出一个快照(参见第 9.27.5 节),它将准确显示数据库的状态,之后所有更改都将包含在更改流中。这可用于通过使用SET TRANSACTION SNAPSHOT
来创建新副本,以读取创建槽时数据库的状态。然后,此事务可用于转储数据库在该时间点的状态,之后可使用槽的内容进行更新,而不会丢失任何更改。
并非总是可以创建快照。特别是,连接到热备用时,它将失败。不需要导出快照的应用程序可以使用NOEXPORT_SNAPSHOT
选项对其进行抑制。