MySql InnoDB设置为自动提交关闭,并使用默认隔离级别可重复读取。有两个场景,两个不同的事务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 t3T1在t3上会产生超时错误,因为它无法捕获T2尚未释放的第2行的写锁,然而,如果T1在t4上提交,则会导致T1的“部分”更新,即第1行被更新,而第2行没有被更新,因此ACID的“原子性”规则被这种实践所违反。
根据ACID的“原子性”规则,事务要么“完成”,要么成功,但不是部分失败。
APP必须请求T1回滚,或者在收到t3错误后在t4提交之前重新尝试超时更新直到成功,从而实现原子性规则。
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传递超时错误,由决定回滚T1的应用程序决定是否回滚,而在2) DB不仅检测死锁错误,而且还会影响到想要死锁的T2。
理论上讲,DB也可以回滚T1,但是在2) DB可能只取消会导致死锁的操作,然后将死锁错误传递给APP,并由APP决定是否回滚T2。
问题在于,当首先在DB级别上检测到错误时,数据库选择应用程序还是它自己应该处理回滚的具体条件。。
非常感谢!
发布于 2010-07-23 10:46:12
回滚应该始终由客户端应用程序处理,而不是数据库。客户端可能作为一个“工作单元”执行许多不同的操作,因此,客户端应该控制该工作何时被组合到数据库或回滚。
参考资料
您可以参考Tom的这个有用链接,他对这个问题感觉非常强烈,甚至建议从PL/SQL中删除提交/回滚(Oracle的过程语言;我知道您的DB是mysql,但概念仍然相同)。
客户端应用程序的另一个令人信服的原因是,唯一能够真正控制事务流的东西应该是 ( a)提交或( b)回滚 它的工作。(与触发器、自治事务以及其他事务一起,如果我有自己的方式,我将取消plsql中的提交和回滚:)
https://stackoverflow.com/questions/3317390
复制相似问题