MySql InnoDB设置为autocommit off并使用默认隔离级别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获得超时错误,因为它无法抓住第2行上的T2尚未释放的写锁定,然而,如果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)数据库只向APP发送超时错误,由APP决定是否回滚T1,但在2)不仅DB检测到死锁错误,而且还用于滚动可能的死锁T2
理论上,在1)DB也可以用来回滚T1,但在2)DB可能只取消导致死锁然后向APP发送死锁错误的操作,由APP决定回滚T2或者不
问题在于,在DB级别上首先检测到错误时,DB选择具体条件来选择APP或其自身是否应该处理回滚。
非常感谢!
答案 0 :(得分:2)
回滚应始终由客户端应用程序处理,不数据库。客户端可能正在执行许多不同的操作作为单个“工作单元”,因此,客户端应该可以控制何时将该工作投入数据库或回滚。
<强>参考强>
你可以参考Tom Kyte的这个helpful link,他对这个问题非常强烈,他甚至建议从PL / SQL中删除提交/回滚(Oracle的程序语言;我知道你的数据库是mysql,但概念仍然是相同)。
另一个引人注目的原因 客户端应用程序,唯一的事情 这真的可以控制交易 流,应该
a)提交或b)回滚
它的工作。 (连同触发器, 自治交易和何时 其他人,我会放弃提交 如果我按照自己的方式在plsql中回滚 :)