TIVK 回滚记录 protect_rollback 细节问题:为何可以不被 protect?

TIKV 代码里面,Rollback 接口正常应该向 write cf 上面写回滚记录。这样即使网络问题,rollback 完成后,prewrite 由于网络原因被重复调用的时候,prewrite 会检测到回滚记录并且终止 prewrite 流程。

然而 Rollback 代码有一个特殊场景,并不会向 write cf 写入回滚记录,代码见:

所以实际上,什么也没有做,连 overlap 也没有设置,那么 prewrite 是如何识别到这种场景,并且阻止 prewrite 流程的呢?还是说什么机制可以保证 rollback 后肯定不会有网络原因导致 prewrite 又被调用?

找到很久之前的一段注释:
https://github.com/tikv/tikv/blob/c3f9fba14b04811e77614bcd50007bad17e251c3/src/storage/mvcc/txn.rs#L692


然后这个注释被一个 issue 打破了:
https://github.com/tikv/tikv/issues/7364
所以后续悲观事务的 primary 被保护起来了。。。
然而乐观事务就没有这个问题了吗?乐观锁是不需要检查 lock 的,为何也可以不被 protect 呢?

2 个赞
  • 对事务 T 使用 Non-protected rollback 意味着已知事务 T 必定被回滚、不可能有并发的其它东西在尝试提交事务 T;这种情况可能发生在事务自身主动进行 rollback (注意不是 rollback 语句,而是 commit 中途失败之后进入的 rollback)。
  • 对事务 T 使用 Protected rollback,意味着不确定事务 T 是否可能被并发地提交,那么需要保证事务必定被回滚,那么需要保证当前写入的 rollback 信息在任何情况下不可以丢弃;而并发的提交过程看到该 rollback 信息便会失败。这种情况可能发生在事务被另一个事务进行 resolve lock 并决定回滚时。

(注:上述回复来自我的同事)

1 个赞

乐观事务 t1 开始进行二阶段提交

  • 发送了 prewrite,tikv 收到了,但是由于网络原因一直没有发送到 tidb 客户端

  • tidb 客户端进行了 prewrite 重试,由于网络原因阻塞,tikv 没有收到。

  • 乐观锁超时

  • 并发事务 t2 调用了 checktxnstatus发现事务已经超时,开始进行 resolve lock,resolve lock 进行了回滚,并且 是 non-protected 级别的,没有任何 rollback 记录

  • 网络原因 tikv 突然又收到了之前的 prewrite

我所说的场景肯定不会出现是吗?

借楼咨询下,这个地方panic代表什么?我自己改代码,遇到了这里panic,没搞明白怎么产生的。

首先 CheckTxnStatus 一定会写入 protected rollback;然后如果你担心的是截图中的 ResolveLock 的处理里面没有设置 protected rollback 导致晚到的 prewrite 可能成功,理论上确实有可能,且乐观悲观都有可能,但是不影响事务正确性,因为在此之前 CheckTxnStatus 一定是写过 protected rollback 的(更严谨地说,对于普通 2PC 事务,primary 一定在 CheckTxnStatus 中被写入 protected rollback;对于 async commit 事务,则也有可能某个 secondary 在 CheckSecondaryLocks 期间写入 protected rollback),于是这个事务必定不可能进入 commit 状态,晚到的 prewrite 写入的锁最终总会在 resolve lock 中被清理

(注:上述回复来自我的同事)

2 个赞

多谢您解惑
这个流程涉及多个接口的交互,的确理解起来比较困难了。我后续可能会为这段代码添加足够的注释,让后面的 contributor 更容易的理解


从 CheckTxnStatus 的代码上面看,好像如果待检查的 primary lock 超时的话,写入的回滚记录并不是保护类型的呢?和您所说的逻辑有出入

1 个赞

乐观锁不检查锁的状态,可能不需要像悲观事务那样进行保护

乐观悲观都有可能,但是不影响事务正确性