我是靠谱客的博主 悲凉画笔,最近开发中收集的这篇文章主要介绍PostgreSQL如何判断事务新旧,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

PostgreSQL由于其多版本特性,经常需要去比较两个事务的新旧。

那么该如何比较两个事务的新旧关系呢?你可能会说通过XID(事务ID)不就可以了,没错!例如一个事务ID是1000000,另一个事务ID是1000001,那么显然是1000000的事务更旧。

但是通过事务ID去判断远不止这么简单,我们都知道pg中的事务ID是用32位无符号数来表示的,也就是说如果不引入特殊的处理,当PostgreSQL的XID 到达40亿,会造成溢出,从而新的XID 为0。

而按照PostgreSQL的MVCC 机制实现,之前的事务就可以看到这个新事务创建的元组,而新事务不能看到之前事务创建的元组,这违反了事务的可见性。这种现象称为XID 的回卷问题。

因此我们比较XID还必须要考虑到回卷的情况。

首先我们需要知道在PG中0,1,2这三个XID的特殊含义:

  • InvalidTransactionId = 0:表示是无效的事务ID
  • BootstrapTransactionId = 1:表示系统表初使化时的事务ID,比任务普通的事务ID都旧。
  • FrozenTransactionId = 2:冻结的事务ID,比任务普通的事务ID都旧。

我们看看PG中是如何比较的:
在这里插入图片描述

上面的代码中if (!TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2))表示当两个XID中有一个不是普通的XID时,那么比较结果直接返回id1 < id2,因为特殊的XID和普通的XID相比,一定是特殊的XID更旧。

而对于都是普通的XID的情况,pg中使用(int32) (id1 - id2),将比较结果转为32位整数。这样做是什么意思呢?

打个比方,如果发生了XID 回卷后,即使id1=4294967290比id2=5(回卷后的XID)大,但因为相减后diff大于2^31,结果值转成int32后会变成一个负数,从而让判断逻辑与事务回卷前都是一样的: (int32)(id1 - id2) < 0。

从而我们可以得出结论:

1. 特殊的事务ID一定比普通的事务ID更旧;
2. 对于都是普通事务ID的情况,PostgreSQL中是使用2^31取模的方法来进行事务的比较。

参考:
src/backend/access/transam/transam.c

最后

以上就是悲凉画笔为你收集整理的PostgreSQL如何判断事务新旧的全部内容,希望文章能够帮你解决PostgreSQL如何判断事务新旧所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部