PostgreSQL 19 - 逻辑订阅端冲突检测增强
PostgreSQL 19 preview - 逻辑订阅端冲突检测增强后续, 检测并报告 update_deleted 冲突
之前的patch刚发了一个框架, 现在后续的功能来了. 支持检测并报告 update_deleted 冲突.
《PostgreSQL 19 preview - 逻辑订阅端冲突检测增强》
Detect and report update_deleted conflicts.
https://github.com/postgres/postgres/commit/fd5a1a0c3e566f7fc860838084466a1c25944281
检测并报告 update_deleted 冲突。
主要内容
该提交增强了 PostgreSQL 逻辑复制的冲突检测能力,能够在订阅端检测并报告“update_deleted”类型的冲突。这种冲突指的是远端节点尝试更新一行,但该行在本地已被其他节点删除的情况。
核心流程:
在 retain_dead_tuples选项启用时,订阅端会保留被删除元组的信息(例如,删除事务的ID、时间戳和origin)。当远端 update 操作在本地找不到对应行时,会额外进行一次全表扫描(SnapshotAny),查找最近被删除但尚未被VACUUM清理的、且符合old值的tuple。 如果发现这样的元组,且删除操作来自不同的origin,则报告 update_deleted 冲突,并记录相关事务及origin信息。 统计信息及监控接口也增加了对这种冲突的计数。
影响的主要文件和逻辑
文档:增加了 update_deleted 类型的冲突说明, retain_dead_tuples选项的行为描述也相应更新。监控视图和统计函数:如 pg_stat_subscription_stats,多了confl_update_deleted字段。复制执行和冲突检测代码大幅增强,支持通过索引或全表扫描查找最近被删除的tuple,比较commit timestamp判断最新的删除。
适用场景举例
场景描述
集群中有A、B两个节点。 用户在A节点发起了 UPDATE tab SET ... WHERE id=1,此时B节点已经将id=1这行删除。如果开启了 retain_dead_tuples,当A节点的update操作通过逻辑复制同步到B节点时,B节点会检测到本地该行已被其他origin删除——此时不会直接报“找不到(update_missing)”,而是更精确地记录为“update_deleted”冲突,并跳过该update。
关键参数
retain_dead_tuples:订阅时需开启此参数。track_commit_timestamp:必须全局开启。相关文档参见 conflict-update-deleted 章节。
SQL 示例
创建发布与订阅时开启参数:
-- 发布端
CREATE PUBLICATION pub FORTABLE tab;
-- 订阅端,注意开启 retain_dead_tuples
CREATE SUBSCRIPTION sub CONNECTION'...' PUBLICATION pub WITH (retain_dead_tuples = true);
检查统计信息(比如订阅端):
SELECT confl_update_deleted
FROM pg_stat_subscription_stats
WHERE subid = (SELECToidFROM pg_subscription WHERE subname = 'sub');
典型冲突日志示例(订阅端日志):
conflict detected on relation "public.tab": conflict=update_deleted ...
DETAIL: The row to be updated was deleted locally in transaction 12345 at 2025-08-04 12:34:56+00.
Remote tuple (1, 3); replica identity (a)=(1)
测试用例参考
详见源码中的 src/test/subscription/t/035_conflicts.pl,有如下自动化测试断言:
ok( $logfile =~
qr/conflict detected on relation "public.tab": conflict=update_deleted.*/
.*DETAIL:.* The row to be updated was deleted locally in transaction [0-9]+ at .*/,
'update target row was deleted in tab');
总结
此提交让 PostgreSQL 的逻辑复制在多主/双向复制场景下,能更准确地检测并区分 update_missing 与 update_deleted 冲突,提高了数据一致性保障能力,并为后续更智能的冲突自动解决打下基础。