如何解释 PostgreSQL txid_current() 值

How to interpret PosgreSQL txid_current() value

我有以下 psql 语句:

假设:初始 txid:a

select txid_current();
----------------------
a+1

begin;
insert into tab( v1,v2);
insert into tab (v3,v4);
commit;

select txid_current();
----------------------
a+3

为什么我看到交易 ID 是 a+3 不应该是 a+2?

txid_current 是如何工作的?

有没有什么有效的方法可以让我只return当前的 txid 而没有额外的增量?

要理解的要点:

  • 一切都在交易中。如果您没有使用 BEGINCOMMIT(或 ROLLBACK)显式创建一个,那么系统会为您创建一个仅针对该语句的。

  • 只读 SELECTs 不会获得完整的交易 ID,它们只会获得虚拟交易 ID。因此,即使它是一个交易,SELECT 1; 或任何不会增加交易 ID 计数器的东西。

  • 调用txid_current()强制分配事务 ID(如果尚未分配的话)。因此,只读事务现在将有一个事务 ID,而以前是没有的。

当然,txids也是跨session分配的。实际上,如果数据库繁忙,您上面的示例可能会得到 txid 的 a+1 和 a+429。

在应用程序级别对任何事物使用事务 ID 通常是不明智的。特别是:

xminxmax视为内部系统级字段,将txid_current()的结果视为无意义的数值。

关于 xid 正确和不正确使用的详细信息

尤其是你不应该:

  • 通过数值比较 xid 以得出有关其排序的任何类型的结论;
  • 添加或减去交易 ID;
  • 排序交易 ID;
  • 增加或减少交易 ID
  • 将 32 位 xid 类型字段与 64 位 bigint 纪元扩展 xid 进行比较,即使相等。

所以从应用程序的角度来看,xid 既不是单调的也不是有序的。

可以安全:

  • 比较两个 64 位历元扩展 xid 是否相等;和
  • 将 xid 传递给 txid_status(...) 以及记录为采用 xid 的其他函数

注意:PostgreSQL 使用像 xid 类型这样的 32 位窄 xid,以及通常表示为 bigint 的 64 位纪元扩展 xid,就像 txid_current()。比较这些是否相等通常似乎适用于新的数据库安装,但一旦第一个纪元环绕发生,它们将不再相等。 Pg 甚至没有给你一个简单的方法来查看 SQL 级别的 xid 纪元;你必须:

select (txid_current() >> 32) AS xid_epoch;

获取txid_current()报告的纪元扩展xid的高32位。

所以...无论您尝试做什么,交易 ID 都可能不是正确的方法。