如何在更新后如何防止SELECT FOR UPDATE中的死锁异常?

时间:2019-01-13 10:06:35

标签: mysql sql mariadb innodb pessimistic-locking

我有一个account表,其中有1行。 我有2个线程可以做下一个:

第一个线程:

begin transaction;
select * from account where balance=0 for update;
UPDATE account SET balance = 10 WHERE balance=0;
// waiting here for several seconds
commit transaction;

第二个线程:

begin transaction;
select * from account where balance=0 for update;
commit transaction;

下一个是流程:
1)第一个线程启动并前进到waiting here for several seconds行。
2)第二个线程启动并被阻止(从逻辑上讲,因为第一个线程尚未释放悲观锁)。
3)第一个线程成功提交事务。
4)第二个线程出错:ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

在这种情况下,如果没有死锁,为什么会出现死锁异常?我在所有4个事务隔离级别上尝试了这种情况,并在所有隔离级别上都获得了相同的错误。

1 个答案:

答案 0 :(得分:1)

问题是我的错误。所以上面的代码实际上应该工作。 我的问题是我在第一个线程中使用了lock in share mode,在第二个线程中使用了for update。我以为它们是相同的,但实际上不是。当我将第一个线程也改为使用for update时,它们开始正常工作。

感谢Shadow给出了使用innodb状态监视器检查死锁事务信息(SHOW ENGINE INNODB STATUS;)的提示。