MySql InnoDB 设置为关闭自动提交并使用默认隔离级别 REPEATABLE READ。有两种不同的事务 T1 和 T2 以下面的时间顺序运行的场景,
1)
time T1 T2
t1 update row 1->OK
t2 update row 2->OK
t3 update row 2->wait->timeout error
t4 commit or rollback or retry t3
T1 在 t3 出现超时错误,因为它无法获取 T2 尚未释放的第 2 行上的写锁,但是,如果 T1 在 t4 提交,它会导致 T1 的“部分”更新,即第 1 行已更新但行2 不是,因此这种做法违反了 ACID 的“原子性”规则。
根据 ACID 的“原子性”规则,事务应该“完成”成功或失败,但不能部分失败。
APP 在 t3 收到错误后,必须在 t4 提交之前请求 T1 回滚或重试超时更新直到成功,从而实现原子性规则。
2)
time T1 T2
t1 update row 1->OK
t2 update row 2->OK
t3 update row 2->wait
t4 update row 1-> DB detects deadlock then forces T2 rolled back
wait->OK
在 1) DB 只将超时错误传递给 APP,由 APP 决定是否回滚 T1,但在 2) 中,DB 不仅检测到死锁错误,而且还采取行动来回滚可能的死锁者 T2。
理论上,1)DB也可以回滚T1,但2)DB可能只会取消导致死锁的操作,然后将死锁错误传递给APP,由APP决定是否回滚T2。
问题在于DB匹配哪些具体条件来选择APP或本身在首先在DB级别检测到错误时是否应该处理回滚。
非常感谢!