如何在事务中使用insert和update语句来防止这种死锁

falq053o  于 2021-06-25  发布在  Mysql
关注(0)|答案(2)|浏览(726)

我有两张table table_a 以及 table_b . 在我的应用程序中,我有一个业务方法,它执行以下操作:

// it is one transaction

INSERT INTO table_b (join_col) VALUES (some_value);

UPDATE table_a a 
JOIN table_b b ON a.join_col = b.join_col AND a.column_a = b.column_b
SET a.column_c = a.column_c + 1;

我使用的是innodb引擎,问题是,当我并行或几乎并行地运行我的方法时,经常会收到以下错误消息:
尝试获取锁时发现死锁;尝试重新启动事务
似乎,第一个事务开始更新 table_a 把门锁上 table_b ,而第二个并行事务不能插入到 table_b ,因为它被锁定了。
如果我评论我的 UPDATE 开始工作了。两个事务都插入到 table_b 没有问题。那么,我该怎么修呢?如果有关系的话,我使用的是mysql 5.7。

piztneat

piztneat1#

看起来你先锁定了b桌,然后锁定了a桌。a锁可能是索引锁。
试试这个,总是先在table上找到一个合适的锁。

BEGIN TRANSACTION;
  SELECT COUNT(join_col) INTO @counter 
    FROM table_a a
   WHERE a.join_col = some_value
     FOR UPDATE;
  INSERT INTO table_b (join_col) VALUES (some_value);
  UPDATE table_a a 
    JOIN table_b b ON a.join_col = b.join_col 
                  AND a.column_a = b.column_b
     SET a.column_c = a.column_c + 1;
COMMIT;

这个 INTO @counter stuff阻止第一个select将结果集返回到程序。
如果这不起作用,请尝试使用锁表。这是一把大锤子,但很有效。

LOCK TABLES table_a, table_b WRITE;
 your queries
UNLOCK TABLES;
n7taea2i

n7taea2i2#

这似乎是奇怪的密码。
在b中插入一组值。
使用所有这些值更新另一个表。
好吧,如果你在另一个线程中使用同一个b,你期望什么?你不希望b中的列表发生变化。
考虑使用 TEMPORARY TABLE 为了b??

相关问题