冲突处理

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

冲突将会产生错误并且停止复制,它可以设置参数,由数据库自动解决,或者用户手工解决。

参数subscription_conflict_resolution可以控制订阅端在主键或唯一键冲突时的处理方式,可以选择是直接报错,还是应用远端或保留本地。设置应用远端时,当insert操作发生冲突时,会将冲突数据更新为同步过来的新元组;当update操作发生冲突时,会先将冲突数据删除,再执行更新操作。设置保留本地时,冲突发生时直接忽略。

注意: 设置应用远端时,当同步过来的新元组存在多行因为不同索引发生冲突时,尝试应用该元组时仍会报错。

此外,在订阅者的服务器日志中可以找到有关冲突的详细情况,如下。

ERROR:  CONFLICT: remote insert on relation t1 (local index t1_idx). Resolution: apply_remote.
DETAIL:  local tuple:  a[integer]:2 b[integer]:10, remote tuple:  a[integer]:3 b[integer]:10, origin: pg_57351, commit_lsn: 0/143A06A0

通过更改订阅者上的数据(这样它就不会与到来的数据发生冲突)或者跳过与已有数据冲突的事务可以解决这种冲突。冲突事务的复制源名称和LSN可以从服务器日志中找到(在上面的例子中,复制源名称是pg_57351,LSN是0/143A06A0)。使用ALTER SUBSCRIPTION SET (SKIPLSN = '0/143A06A0')可以跳过产生冲突的事务。也可以通过调用pg_replication_origin_advance()函数跳过该事务,函数的参数是对应于该订阅名称的node_name(即pg_57351)以及commit_lsn的下一个LSN(即0/143A06A1)。复制源头的当前位置可以在pg_replication_origin_status系统视图中看到。请注意,跳过整个事务包括跳过可能不违反任何约束的更改,使得发布端和订阅端数据不一致。

意见反馈
编组 3备份
    openGauss 2024-04-27 00:42:12
    取消