哪个应该在回滚,App或DB上主动完成任务?

问题描述 投票:2回答:1

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或其自身是否应该处理回滚。

非常感谢!

mysql database transactions rollback acid
1个回答
2
投票

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

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

客户端应用程序的另一个令人信服的理由是,唯一可以真正控制事务流的事情应该是

a)提交或b)回滚

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

© www.soinside.com 2019 - 2024. All rights reserved.