2

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级别检测到错误时是否应该处理回滚。

非常感谢!

4

1 回答 1

2

回滚应始终由客户端应用程序处理,而不是数据库。客户端可能会作为单个“工作单元”执行许多不同的操作,因此,客户端应该控制何时将该工作提交到数据库或回滚。

参考
你可以参考 Tom Kyte 的这个有用的链接,他对这个问题感觉非常强烈,甚至建议从 PL/SQL(Oracle 的过程语言;我知道你的数据库是 mysql,但概念保持不变)中删除提交/回滚.

CLIENT APPLICATION 的另一个令人信服的理由,唯一可以真正控制交易流的东西,应该要么

a) 提交或 b) 回滚

这是工作。(连同触发器、自主事务和其他事务,如果我有办法的话,我会取消 plsql 中的提交和回滚:)

于 2010-07-23T10:46:12.723 回答