通过 DEBUG tikv 的代码:
可以总结有两种场景:
-
如果只有悲观事务,那么 RC/RR 级别的 select 快照读会忽略其他悲观事务加的锁。例如有两个悲观事务,一个事务t1 执行 select for update,不提交,另一个事务 t2 执行 select 快照读。虽然 t2 快照读发送给 tikv 的请求仍然是 si 级别的,也检测到了 t1 事务所加的悲观锁,但是会主动忽略这个锁,而直接返回上一个 commit 记录,无需等锁或者重试
-
如果悲观事务和乐观事务共存,RC/RR 级别的 select 快照读可能会遭遇等锁、重试。例如两个事务,一个事务是乐观事务 t1,当前正在进行二阶段提交,目前刚刚 prewrite 完成,还未能 commit。事务 t2 是悲观事务,执行 rc 级别的快照读,此时快照读拿到时间戳 read_ts2。这个时候 t2 的快照读会检测到 t1 的 lock 乐观锁。如果无法确定这个乐观锁最后提交的时间 commit_ts1 到底会大于 read_ts2 还是小于 read_ts2,因此需要等锁、重试。防止事务 t2 快照读成功后,突然又有乐观事务把事务提交到了 read_ts2 之前,正确性得到了提升。
第二种情况同样适用于悲观事务进行二阶段提交时,prewrite 完成后,因为此时悲观事务的悲观锁被修改为乐观锁。