use*_*434 4 sql transactions database-deadlocks
场景:
事务A开始...
START TRANSACTION;
UPDATE table_name SET column_name=column_name+1 WHERE id = 1 LIMIT 1;
Run Code Online (Sandbox Code Playgroud)
与此同时,事务B开始......
START TRANSACTION;
UPDATE table_name SET column_name=column_name+1 WHERE id = 2 LIMIT 1;
UPDATE table_name SET column_name=column_name-1 WHERE id = 1 LIMIT 1;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
现在,事务 B 正在等待行 1,该行被锁定在事务 A 中。
交易A继续进行……
UPDATE table_name SET column_name=column_name-1 WHERE id = 2 LIMIT 1;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
现在我们遇到了死锁,因此两个事务都在等待对方解锁它们想要更新的行:'(
正如我在标题中所问的,我们如何防止 RDBMS 事务中的死锁?
我认为解决这种情况的唯一方法是我们回滚事务B并重新执行它。但是我们如何才能发现自己陷入了僵局,并立即摆脱困境,如何保证我们不会陷入死循环(例如,在非常繁重的 Web 应用程序上)。
如果有必要,我会使用 MySQL。但任何适用于其他 RDBMS 的解决方案都是受欢迎的 - 帮助其他从 Google 来到这里的人:)
大多数数据库(如果不是全部)都会自动检测死锁,选择一个会话作为受害者,并自动回滚该会话的事务以打破死锁。例如,这里是MySQL死锁检测和回滚文档。
死锁是编程错误。避免死锁的一个简单解决方案是确保始终按特定顺序锁定行。例如,如果您有一个事务想要更新两个不同的行,请始终更新较小的id第一个行和较大的id第二个行。如果您的代码总是这样做,那么至少不会出现行级死锁。除此之外,为代码中的关键部分实现适当的序列化。具体来说,这需要什么很大程度上取决于您的应用程序。
| 归档时间: |
|
| 查看次数: |
8486 次 |
| 最近记录: |