逻辑复制的行为类似于普通 DML 操作:即使订阅节点上的数据已在本地被修改, 传入的数据仍会更新它。如果传入数据违反任何约束,复制就会停止。这称为 冲突。在复制 UPDATE 或 DELETE 操作时,找不到数据不会产生冲突,这类操作会被直接跳过。
逻辑复制操作会以订阅所有者角色的权限执行。目标表上的权限失败会导致复制冲突, 目标表上启用的行级安全也会导致复制冲突,只要订阅所有者受其约束,而不管任何策略 是否通常会拒绝正在复制的 INSERT、UPDATE、 DELETE 或 TRUNCATE。这一行级安全限制 可能会在 PostgreSQL 的未来版本中取消。
冲突会产生错误并停止复制;必须由用户手工解决。冲突的详细信息可以在订阅端的 服务器日志中找到。
解决方法可以是在订阅端更改数据或权限,使其不再与传入变更冲突;也可以跳过与现有 数据冲突的事务。当冲突导致错误时,复制不会继续,逻辑复制工作者会向订阅端的 服务器日志输出如下消息:
ERROR: duplicate key value violates unique constraint "test_pkey" DETAIL: Key (c)=(1) already exists. CONTEXT: processing remote data for replication origin "pg_16395" during "INSERT" for replication target relation "public.test" in transaction 725 finished at 0/14C0378
事务的 LSN 和复制源名称可以从服务器日志中找到(上述示例中的 LSN 为 0/14C0378,复制源为 pg_16395)。可以使用 ALTER SUBSCRIPTION ... SKIP 并提供 finish LSN (即 LSN 0/14C0378)来跳过导致冲突的事务。finish LSN 可以是事务在发布端提交 或准备完成时的 LSN。或者,也可以通过调用 pg_replication_origin_advance() 函数来跳过该事务。 在使用该函数之前,需要先临时禁用订阅,可以使用 ALTER SUBSCRIPTION ... DISABLE,或者将订阅与 disable_on_error 选项一起使用。然后,可以使用 pg_replication_origin_advance(),传入 node_name(即 pg_16395)以及 finish LSN 的下一个 LSN(即 0/14C0379)。当前各个复制源的位置可以在 pg_replication_origin_status 系统视图中查看。 请注意,跳过整个事务也会跳过那些本来不会违反任何约束的变更,这很容易使订阅端 变得不一致。
当 streaming 模式为 parallel 时,失败事务的 finish LSN 可能不会被记录。 在这种情况下,可能需要把 streaming 模式改为 on 或 off,并再次制造相同冲突,以便把失败事务的 finish LSN 写入 服务器日志。关于 finish LSN 的用法,请参见 ALTER SUBSCRIPTION ... SKIP。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。