可见性判断考虑的因素
- 事务是单事务还是多事务
- xmin,与 xmax 事务
- 事务正在进行还是已经提交了
- xmax 是加锁还是真的更新
HeapTupleSatisfiesUpdate 具体过程
- 查看infomask,xmin 提交了(HEAP_XMIN_COMMITTED),说明这个元组创建成功。
- 如果没有提交
- 如果 infomask 为 HEAP_XMIN_INVALID,说明abort了,则不可见
- 如果是当前事务创建的元组
- 读取创建元组的 commandId,如果 commandId 在自己事务之后,则不可见。
- 如果 command 在自己之前,xmax 不是有效 id,说明则这个元组有不可见的可能性,返回 HeapTupleMayBeUpdated。
- 如果这个元组有 xmax,但这个 xmax 只是锁定行(infomask有HEAP_XMAX_LOCK_ONLY标记)
- 如果这个 xmax 事务是多 command 的事务(infomask 标记 HEAP_XMAX_IS_MULTI)
- 这个 xmax 事务锁定了这个元组(像 select for update 的语句) ,则有更新它的可能,返回 HeapTupleMayBeUpdated
- 如果没有被锁定,但还是有活着的子事务,则同样有更新可能 ,返回 HeapTupleMayBeUpdated
- 否则返回 HeapTupleBeingUpdated
- 如果这是一个单命令事务,且不进行中(在RecentXmin之前或缓存中显示提交了,或查每个进程中的事务显示没有这个进程,或clog显示事务 abort了)则返回 HeapTupleBeingUpdated
- 如果在进行中且不是自己事务,则返回 HeapTupleBeingUpdated
- 如果 xmax 不是锁定行,且是多命令事务
- xmax 不是自己事务,且 xmax 有子事务在进行中,返回 HeapTupleBeingUpdated,否则 xmax 的事务一定会 abort 因为这个元组是我自己创建的,返回 HeapTupleMayBeUpdated。
- 如果 xmax 是自己事务,就查看 cmax,如果在自己这个命令id前发生,则返回不可见,如果cmax在自己之后,则可见
- 对于 xmax 是单事务的情况,如果 xmax 不是自己,那那个事务肯定会abort,因为这个元组是我自己创建的,标记xmax_invalid(更新前要确认xlog刷盘了),返回HeapTupleMayBeUpdated
- 如果 xmax 是自己(自己是单事务)且cmax在自己commandid之后,则返回 HeapTupleSelfUpdated
- 否则删除元组的 cmax 在自己之前,返回 invisible
- 如果 xmin 正在进行中,返回不可见
- 如果查看 clog 发现确实 xmin 提交了,就更新元组的 HEAP_XMIN_COMMITTED 信息(更新前要确认xlog刷盘了)
- 如果 xmin 没有提交又不在进行中,说明 abort 了,标记 HEAP_XMIN_INVALID(更新前要确认xlog刷盘了),返回不可见
- xmin 事务已经提交了,xmax 是 invalid,则返回 HeapTupleMayBeUpdated
- xmin 事务已经提交了,xmax 是 commit 的
- 如果xmax 只是对元组加锁,返回 HeapTupleMayBeUpdated
- 否则确实是删除了这个元组,返回 HeapTupleUpdated
- xmin 事务已经提交了,xmax 是多事务
- xmax 对行加锁且是share锁,返回 HeapTupleMayBeUpdated
- xmax 对行只是加锁,如果事务在进行,返回HeapTupleBeingUpdated,
- 如果没有在进行了,标记 HEAP_XMAX_INVALID(更新前要确认xlog刷盘了)返回 HeapTupleMayBeUpdated
- xmax 没有加锁,xmax 是自己,根据 cmax 在自己 cid 之前的返回HeapTupleSelfUpdated,之后的返回不可见
- xmax 不是自己且正在进行的,返回 HeapTupleBeingUpdated
- xmax 不是自己且在 clot 显示提交了,返回 HeapTupleUpdated
- xmax 不是自己且没提交,则要查看它是不是还在运行(在RecentXmin之前或缓存中显示提交了,或查每个进程中的事务显示没有这个进程,或clog显示事务 abort了,则这个事务没有在运行),没有运行了则标记 HEAP_XMAX_INVALID(更新前要确认xlog刷盘了),返回 HeapTupleMayBeUpdated
- 否则 xmax 还在运行中,返回 HeapTupleBeingUpdated
- 单事务 xmax 是自己
- 如果是自己对行上锁,返回 HeapTupleMayBeUpdated
- 如果是自己没有上锁,根据 cmax 与自己 cid 的关系返回 HeapTupleSelfUpdated 或不可见。
- 单事务不是自己,且正在进行中,返回 HeapTupleBeingUpdated
- 单事务不是自己,且查 clog 发现没有提交,则标记 HEAP_XMAX_INVALID(更新前要确认xlog刷盘了),返回 HeapTupleMayBeUpdated
- 单事务 xmax 不是自己, 提交了,如果只是加锁,则标记 HEAP_XMAX_INVALID(更新前要确认xlog刷盘了),返回 HeapTupleMayBeUpdated
- 否则单事务 xmax 提交了,且不只是加锁,说明真的删除了,标记 HEAP_XMAX_COMMITTED(更新前要确认xlog刷盘了),返回 HeapTupleUpdated
处理
- HeapTupleInvisible:报错回滚
- HeapTupleBeingUpdated:等待 xmax
- HeapTupleMayBeUpdated:根据快照判断可见与否
- HeapTupleUpdated / HeapTupleSelfUpdated / HeapTupleBeingUpdated:跳过这个元组