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 行已更新,但第 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层面检测到错误时,DB需要满足什么具体条件来选择APP或本身是否应该处理回滚。
多谢!
回滚应始终由客户端应用程序处理,not数据库。客户端可能将许多不同的操作作为单个“工作单元”执行,因此,客户端应该能够控制何时将该工作提交到数据库或回滚。
参考
你可以参考这个有用的链接 https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:73833357590501来自 Tom Kyte,他对这个问题的感受如此强烈,以至于他甚至建议从 PL/SQL(Oracle 的过程语言;我知道你的数据库是 mysql,但概念保持不变)中删除提交/回滚。
另一个令人信服的理由
客户应用程序,唯一的事情
真正可以控制交易
流,应该
a) 提交或 b) 回滚
是工作。 (与触发器一起,
自主交易以及何时
其他人,我会取消提交
如果我有办法的话,可以在 plsql 中回滚
:)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)