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

How to prevent Deadlock exception in SELECT FOR UPDATE after the update?

我有一个 account table 有 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;

第 2 个线程:

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 个事务隔离级别尝试了这个场景,并且所有隔离级别都获得了相同的错误。

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

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