这是检查 Postgres 是否提交事务 ID 的正确方法吗

Is this a right way to check if Postgres Committed a Transaction id

在Postgresql中,如果事务id是“123456”,table名称是"table1"那么我是否可以执行下面的查询? :

Select count (*) from table1 where xmin=123456 OR xmax=123456

如果计数 returns 值 > 1,那么我可以假设事务 ID 已提交吗?

_

注:

  1. 交易 ID 从不同的 java 程序发送到另一个 java 通过 RMI (OR) TCP Sockets (OR) File (OR) 一些其他机制编程
  2. 事务 ID 是从更新、插入、删除之后收集的 触发器
  3. 在这些操作期间不执行真空或任何其他维护程序
  4. 也不用担心 txid 环绕问题

当使用 oracle 时,v$transaction 来拯救... 但是在 Postgres 中,我找不到类似的东西... 虽然一些谷歌搜索让我相信有办法使用 "pg_log" 文件或 "pg_locks" 视图 找到它,但我不知道如何

我唯一能想到的肮脏方法是 xmin 和 xmax...我什至无法判断这是否是一个肮脏的方法

有没有 Postgresql 老师可以指导我正确的方向?

更新:

对于 postgresql 9.5 及更高版本,"laurenz albe" 的答案是完美的... 对于那些使用 Postgresql 9.0 到 9.3 的人,你应该使用,

SELECT count(xmin) as SIZE FROM table1 WHERE xmin = 123456 AND xmax = 0

此外,当删除操作发生并且您获得事务 ID 时,我们需要以不同的方式检查它...

SELECT count(xmin) as SIZE FROM table1 WHERE xmin = 123456 OR xmax = 123456

然后查看结果。如果它 returns 为零,则提交删除操作...如果结果为非零,则回滚事务,您无需担心未提交的事务

注: 这是为了检查从触发器接收并发送到另一个外部程序(java)的事务 ID 是否已提交且未回滚并且数据库会话不同...

如果您看到 xmin=123456 并且您的 txid_current() <> 123456 是 - 那么事务 123456 已提交。

postgres 中没有 transactionId 这样的列。

xmax 的测试是错误的。

当行版本(PostgreSQL 中的 元组 )被 UPDATEDELETE 标记为无效时,

xmax 被设置。意思是后面的交易ID的交易都看不到这个元组,一旦再也看不到它就可以回收

如果事务被回滚,xmax的值不会被重置——事务状态存储在提交日志中,并且元组仍然可见其他。

但是xmax也是用来存储行锁的

因此,如果您可以在 xmax = '123456' 处看到一个元组,则表示以下之一:

  • 元组已删除或更新,事务已提交,但您的事务快照较旧,因此您仍然看到旧元组。

  • 元组被删除或更新,事务被回滚。

  • 元组被事务 123456 锁定,例如SELECT ... FOR UPDATE.

另一方面,如果您看到带有 xmin = '123456' 的元组并且这不是您当前的事务,您可以确定该事务已提交。

所以你的测试应该是

SELECT count(*) FROM table1 WHERE xmin='123456';

但这是一个 糟糕的 查询。它强制对整个 table 进行顺序扫描,并且不允许在系统列上建立索引。

如果您使用的是 PostgreSQL 9.5 或更新版本,请考虑激活 track_commit_timestamp and using the function pg_xact_commit_timestamp(xid)。对于未提交的事务,它将 return NULL。