我有两张表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。
答案 0 :(得分:1)
看起来你正在锁定表b,然后表a。可能锁是一个索引锁。
试试这个,总是首先抓住桌子上适当的锁。
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
内容会阻止第一个SELECT将结果集返回给您的程序。
如果不起作用,请尝试使用LOCK TABLES。这是一个很大的锤子,但很有效。
LOCK TABLES table_a, table_b WRITE;
your queries
UNLOCK TABLES;
答案 1 :(得分:0)
这看起来很奇怪。
好吧,如果你在另一个帖子中玩相同的 B,你期望什么?您不希望B中的事物列表发生变化。
考虑使用local normalizedString = str:gsub("[%z\1-\127\194-\244][\128-\191]*", tableAccents)
代替B ??