【问题标题】:How to prevent Deadlock exception in SELECT FOR UPDATE after the update?如何防止更新后SELECT FOR UPDATE出现死锁异常?
【发布时间】:2019-01-13 10:06:34
【问题描述】:

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

【问题讨论】:

  • 使用 innodb 状态监视器找出究竟是什么导致了死锁。
  • @Shadow 谢谢。我会尝试监控它,然后我会更新问题。

标签: mysql sql mariadb innodb pessimistic-locking


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2019-06-13
    • 1970-01-01
    • 2020-11-24
    • 2010-10-31
    • 1970-01-01
    • 2013-10-19
    • 1970-01-01
    • 2015-10-21
    • 1970-01-01
    相关资源
    最近更新 更多