9.3 9.4 9.5 9.6 10 11 12 13 14 Current(15)
阿里云PostgreSQL 问题报告 纠错本页面

31.5. 冲突

逻辑复制的行为类似于正常的DML操作,即便数据在订阅者节点本地被修改,逻辑复制也会根据收到的更改来更新数据。如果流入的数据违背了任何约束,复制将停止。这种情况被称为一个冲突。在复制UPDATEDELETE操作时,缺失的数据将不会产生冲突并且这类操作将被简单地跳过。

逻辑复制操作是以拥有订阅的角色的权限执行的。目标表上的权限失败将导致复制冲突, 同样,目标表上启用的行级安全性也会导致冲突, 而不考虑订阅所有者是否受到任何策略通常会拒绝正在复制的INSERTUPDATEDELETETRUNCATE。 对行级安全性的这种限制可能在未来版本的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()函数和完成LSN的下一个LSN(即0/14C0379)来使用node_name(即pg_16395)。 可以在 pg_replication_origin_status系统视图中查看源的当前位置。 请注意,跳过整个事务包括跳过可能不违反任何约束的更改。这可能会使订阅者不一致。