《postgresql指南--内幕探索》第五章并发控制(二)

本文深入探讨了PostgreSQL的事务隔离级别,包括READ COMMITTED和REPEATABLE READ,以及如何通过可见性检查规则避免脏读、不可重复读。文章通过实例解释了事务间的可见性规则,如Rule1至Rule10,并展示了在不同隔离级别下并发事务的执行情况。此外,还讨论了防止更新丢失的机制,特别是如何处理LostUpdate问题。最后,介绍了可序列化快照隔离(SSI)机制,用于防止序列化异常和幻读,以及冻结处理来解决事务ID回卷问题。
可见性检查规则

可见性检查规则是一组规则,用于确定一条元组是否对于一个事务可见。该规则会用到:

1.tuple中的t_xmin和t_xmax字段;
2.clog
3.当前的snapshot

为了简便起见,在此回避了子事务和有关t_ctid的问题,只讨论最简单的情形。

我们选取十条规则并将他们分为三类进行说明。

t_xmin的状态为ABORTED

我们知道t_xmin是一个tuple被INSERT时的事务txid。如果该事务的状态为ABORTED,说明该事务被取消,那么理所当然该事务所INSERT的tuple自然是无效并且是不可见的。所以Rule1即为:

Rule 1: If Status(Tuple.t_xmin) = ABORTED ⇒ Tuple is Invisible

t_xmin的状态为IN_PROGRESS

如果一个tuple的t_xmin的状态为IN_PROGRESS,那么很大可能它是不可见的。

因为:

如果这个tuple是其它事务(非当前事务)所插入的,那么这个tuple显然是不可见的,因为这个tuple还未提交(postgreSQL不支持读未提交)。

Rule 2: If Status(t_xmin) = IN_PROGRESS && t_xmin ≠ current_txid ⇒ Tuple is Invisible

如果这个tuple是当前事务提交的,并tuple的t_xmax值不是0,即该tuple是由当前事务插入,但是被当前事务UPDATE或者DELETE过了,因此,显然是不可见的。

Rule 3: If Status(t_xmin) = IN_PROGRESS && t_xmin = current_txid && t_xmax ≠ INVAILD ⇒ Tuple is Invisible

反之,如果这个tuple是当前事务提交的,并tuple的t_xmax值是0,说明这个tuple是由当前事务插入并且并没有被修改过,所以,它是可见的。

Rule 4: If Status(t_xmin) = IN_PROGRESS && t_xmin = current_txid && t_xmax = INVAILD ⇒ Tuple is Visible

t_xmin的状态为COMMITTED

和上面的相反,如果一个tuple的t_xmin的状态为COMMITTED,那么很大可能它是可见的。

先把规则列出来,后面再解释。

Rule 5: If Status(t_xmin) = COMMITTED && Snapshot(t_xmin) = active ⇒ Tuple is Invisible

Rule 6: If Status(t_xmin) = COMMITTED && Snapshot(t_xmin) ≠ active && (t_xmax = INVALID || Status(t_xmax) = ABORTED) ⇒ Tuple is Visible

Rule 7: If Status(t_xmin) = COMMITTED && Status(t_xmax) = IN_PROGRESS && t_xmax = current_txid ⇒ Tuple is Invisible

Rule 8: If Status(t_xmin) = COMMITTED && Status(t_xmax) = IN_PROGRESS && t_xmax ≠ current_txid ⇒ Tuple is Visible

Rule 9: If Status(t_xmin) = COMMITTED && Status(t_xmax) = COMMITTED && Snapshot(t_xmax) = active ⇒ Tuple is Visible

Rule 10: If Status(t_xmin) = COMMITTED && Status(t_xmax) = COMMITTED && Snapshot(t_xmax) ≠ active ⇒ Tuple is Invisible

Rule5是比较显然的,对于一个tuple,插入它的事务已经提交(COMMITED),并且该事务在当前的snapshot下是active的,说明该事务对当前事务中的命令来说是 in progress 或者 not yet started,故该事务插入的tuple对在当前为不可见;

Rule6,显然,该tuple没有被修改或者修改它的事务被abort了 = > 该tuple没有被修改;插入该tuple的事务x在当前snapshot中是inactive(inactive说明事务x对于当前要执行的SQL命令来说要么被提交了,要么被abort了),所以可见;

Rule7,如果tuple被当前事务UPDATE或者DELETE了,自然这个tuple对于我们来说是旧版本了,不可见;

Rule8,和Rule7对比,这个tuple是被别的事务x修改(UPDATE或者DELETE)了,而且事务x没有被提交(postgreSQL不支持读未提交),所以修改后的元组对我们不可见,我们能看到的还是当前这个元组,所以当前tuple可见;

Rule9,虽然修改这个tuple的事务x已经提交了,但是事务x在当前snapshot中是active的,即对当前事务中的命令来说是 in progress 或者 not yet started(第二次用到这个假设了),所以事务x的修改对当前命令不可见,所以我们看到了还是这个tuple;

Rule10,和上一条相反,修改这个tuple的事务x已经提交了,并且事务x在当前snapshot中是inactive(inactive说明事务x对于当前要执行的SQL命令来说要么被提交了,要么被abort了)的,所以对当前事务中的命令来说,这个事务x已经提交,所以这个tuple对当前事务中的命令而言,已经是被修改过了,即是旧版本的了,所以即为不可见。

可见性检查
可见性检查的规则

在这里插入图片描述
简化起见,txid=200的事务的隔离级别为READ COMMITTED,txid=201的事务的隔离级

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值