第 48 章 复制进度跟踪
复制源旨在让在逻辑解码之上实现逻辑复制方案变得更容易。它们为两个常见问题提供了解决方案:
如何安全地跟踪复制进度
如何根据一行数据的来源改变复制行为;例如,在双向复制拓扑中防止形成环路
复制源只有两个属性:名称和 OID。名称是在系统之间引用该复制源时应使用的标识,它是自由形式的 text 值。使用它时,应尽量降低不同复制方案创建的复制源之间发生冲突的概率;例如,可以在前面加上复制方案的名称作为前缀。OID 仅用于在空间效率很重要的场合避免存储较长的名称形式。它绝不应在不同系统之间共享。
可以使用函数
pg_replication_origin_create() 创建复制源;使用
pg_replication_origin_drop() 删除复制源;并可在
pg_replication_origin
系统目录中查看它们。
构建复制方案时,一个并不简单的部分是要以安全的方式跟踪重放进度。当应用进程或整个集簇崩溃时,必须能够找出数据已经成功复制到了哪里。对此的一些朴素解决方案,例如每重放一个事务就更新表中的某一行,会带来运行时开销和数据库膨胀等问题。
借助复制源基础设施,可以将一个会话标记为正在重放来自远程节点的数据(使用函数
pg_replication_origin_session_setup())。此外,还可以使用
pg_replication_origin_xact_setup()
按事务为每个源事务配置其 LSN 和提交时间戳。这样做之后,复制进度就会以崩溃安全的方式持久保存。所有复制源的重放进度都可以在
pg_replication_origin_status
视图中查看。某个单独复制源的进度,例如在恢复复制时,可以通过
pg_replication_origin_progress()(适用于任意复制源)或
pg_replication_origin_session_progress()(适用于当前会话中配置的复制源)来获取。
在比恰好从一个系统复制到另一个系统更复杂的复制拓扑中,另一个问题在于很难避免再次复制已经重放过的行。这既会导致复制出现环路,也会带来低效。复制源提供了一种可选机制来识别并防止这种情况。当使用前一段提到的函数进行配置后,传递给输出插件回调(见第 47.6 节)的每一项变更和事务,都会带上其生成会话的复制源标记。这使得输出插件可以区别对待它们,例如忽略所有并非源自本地的行。此外, filter_by_origin_cb 回调还可用于根据来源过滤逻辑解码变更流。虽然灵活性较低,但通过该回调进行过滤要比在输出插件中自行过滤高效得多。