子事务 ID 消耗哪些资源?

What resources do subtransaction IDs consume?

The PostgreSQL wiki 建议一种使用重试循环实现 UPSERT 的方法。此解决方案中隐含使用 "subtransaction IDs"。在维基文章中有以下警告:

The correct solution is slow and clumsy to use, and is unsuitable for significant amounts of data. It also potentially burns through a lot of subtransaction IDs - avoiding burning XIDs is an explicit goal of the current "native UPSERT in PostgreSQL" effort.

使用"a lot of subtransaction IDs"的后果是什么?我真的不知道子交易 ID 是什么 - 这只是一种对嵌套交易进行编号的方式吗,是否暗示这些数字可能 运行 出来?

资源是 32 位 XID 事务计数器本身,引擎使用它来了解 table 中行的版本是否关联到 "old"事务(已提交或回滚)或尚未提交的事务,以及它在任何给定事务中是否可见。

以超高速率增加 XID 会产生或增加出现事务 ID 环绕 问题的风险。最坏的情况是此问题升级为数据库自动关闭以避免数据不一致。

避免事务 ID 回绕的是例行清理。 Preventing Transaction ID Wraparound Failures.

下的文档对此进行了详细说明

但是 autovacuum 是后台任务,不会妨碍前台 activity。除其他外,它会取消自身而不是锁定其他查询。有时,它可能会落后很多。

我们可以想象一个最坏的情况,即前台数据库 activity 增加 XID 值的速度如此之快,以至于 autovacuum 没有时间在这些 XID 值被删除之前冻结具有 "old XIDs" 的行被新事务或子事务声明,这是 PostgreSQL 无法处理的情况。

也可能是这些前台事务在发生这种情况时仍未提交,因此即使是激进的真空也无能为力。

这就是为什么程序员应该谨慎对待使此事件更有可能发生的技术,例如 opening/closing 大循环中的子事务。

范围大约是 20 亿笔交易,但这是系统设计时无法达到的限制,但随着我们的硬件能力和我们从数据库中请求的内容不断变化,这将成为问题-增加。