可见性判断考虑的因素

  1. 事务是单事务还是多事务
  2. xmin,与 xmax 事务
  3. 事务正在进行还是已经提交了
  4. xmax 是加锁还是真的更新

HeapTupleSatisfiesUpdate 具体过程

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

处理

  • HeapTupleInvisible:报错回滚
  • HeapTupleBeingUpdated:等待 xmax
  • HeapTupleMayBeUpdated:根据快照判断可见与否
  • HeapTupleUpdated / HeapTupleSelfUpdated / HeapTupleBeingUpdated:跳过这个元组