【问题标题】:Is this a right way to check if Postgres Committed a Transaction id这是检查 Postgres 是否提交事务 id 的正确方法吗
【发布时间】:2017-07-04 09:38:00
【问题描述】:

在 Postgresql 中,如果事务 id 是“123456”,表名是“table1”,那么我可以执行以下查询吗? :

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

如果 count 返回值 > 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

然后检查结果。如果返回零,则提交删除操作...如果结果为非零,则事务回滚,您不必担心未提交的事务

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

【问题讨论】:

  • 所以您只想知道 table1 中是否存在 transactionId 为 123456 的行?为什么不select count(*) from table1 where transactionId='123456'
  • @DaveH 我不知道有一个名为 transactionId 的系统列它会在 postgres 9.0 和 9.3 中工作吗?
  • 请不要为问题添加可能的解决方案。问题应仅包含问题本身的一部分信息。
  • @RealSkeptic,哎呀对不起...删除它...
  • @DaveH,您确定有一个名为 transactionId 的系统列吗?因为当我在postgresql docs 中查看时,我找不到它...

标签: java database postgresql transactions ipc


【解决方案1】:

xmax 的测试错误。

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

xmax 被设置。意思是后面的事务ID的事务都看不到这个元组,一旦没人能看到就可以回收。

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

xmax也用于存储行锁。

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

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

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

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

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

所以你的测试应该是

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

但这是一个可怕的查询。它强制对整个表进行顺序扫描,并且不允许对系统列进行索引。

如果您使用的是 PostgreSQL 9.5 或更高版本,请考虑激活 track_commit_timestamp 并使用函数 pg_xact_commit_timestamp(xid)。对于未提交的事务,它将返回 NULL。

【讨论】:

  • postgresql 9.5?我陷入困境...我正在寻找 9.0 到 9.3 的解决方案...我会将其标记为答案,但这并不能解决我的问题...
  • 还有其他解决方案吗?如果没有,我会在你提到的时候使用TERRIBLE 查询......但至少我会有一个解决方案......总比没有好......
  • 我在答案的最后一段中提供了替代解决方案。
  • 感谢您的努力...我使用 Postgresql 9.3 并期望与 9.0 兼容,这就是为什么我决定将查询与 xmin 一起使用而不是 pg_xact_commit_timestamp(xid),它不适用于 9.3,更不用说 9.0
【解决方案2】:

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

postgres 中没有transactionId 这样的列。

【讨论】:

  • 这是正确的方法吗?...或者还有其他微妙的方法吗?或任何有效的方法?如果是这样,我会将其标记为正确答案...请确认...
  • 事实上我已经忘记了v$transaction,因为我已经很多年没有使用Oracle了。而且我不记得在 Postgres 中有任何类似的东西。要到达 pg_locks 你必须锁定关系并且transactionid 不一定会被填充。所以我想说你的方法看起来很合理
  • 这是不正确的。如果您看到xmax,并不表示事务已提交。
  • @CrystalPaladin 请查看 Laurenz Albe 的回答 - 我希望您接受他的回答而不是我的回答
猜你喜欢
  • 1970-01-01
  • 2018-09-18
  • 2014-06-13
  • 2020-02-14
  • 2016-05-10
  • 1970-01-01
  • 2021-12-13
  • 1970-01-01
  • 2021-10-10
相关资源
最近更新 更多