逻辑复制的行为类似于正常的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
命令跳过产生冲突的事务,
并使用完成的LSN(即LSN 0/14C0378)。完成的LSN可以是事务在发布者上提交或准备的LSN。
或者,也可以通过调用
pg_replication_origin_advance()
函数来跳过事务。
在使用此函数之前,需要暂时禁用订阅,可以通过
ALTER SUBSCRIPTION ... DISABLE
命令禁用订阅,
或者可以使用带有
disable_on_error
选项的订阅。
然后,您可以使用pg_replication_origin_advance()
函数,
并提供node_name
(即pg_16395
)
和完成LSN的下一个LSN(即0/14C0379)。可以在
pg_replication_origin_status
系统视图中查看源的当前位置。
请注意,跳过整个事务包括跳过可能不会违反任何约束的更改。
这可能会很容易导致订阅者不一致。
当
流式
模式为并行
时,失败事务的完成LSN可能不会被记录。在这种情况下,
可能需要将流式模式更改为开启
或关闭
,并再次
触发相同的冲突,以便失败事务的完成LSN会被写入服务器日志。关于完成LSN的使用,请
参考ALTER SUBSCRIPTION ...
SKIP
。