MySQL UPDATE / DELETE 死锁使用模

MySQL UPDATE / DELETE deadlock using modulo

提问人:Ecuador 提问时间:11/10/2023 最后编辑:Ecuador 更新时间:11/10/2023 访问量:28

问:

我有一个表,其中有一列,它是一个整数索引。有许多进程必须选择不冲突的用户并进行一些处理。我为此使用模数,所以在某些时候,他们会这样做(例如,在 4 个线程的情况下):user_id

UPDATE table SET data = x WHERE user_id % 4 = y;

其中 y 为 0 到 3,用于标记哪个特定线程正在工作。不幸的是,MySQL不能像这样使用user_id索引,所以它似乎锁定了所有表来扫描它。如果它只有一个 READ 锁,这会导致死锁,而另一个进程正在执行如下操作:

DELETE FROM table WHERE user_id = z;

您认为解决这个问题的最佳方法是什么?

我想我可以有一个单独的查询,得到结果(这将是几百个),然后用一个来代替。 我不确定锁如何用于嵌套选择,所以也许可以:SELECT user_id FROM table WHERE user_id % 4 = yuser_id IN (...)

UPDATE table SET data = x WHERE user_id IN (SELECT user_id from table WHERE user_id % 4 = y)

也工作,以避免获取 SELECT 结果来执行 UPDATE?

否则我想我可以使用 LOCK TABLES 等,但我认为这不太好,所以我很好奇是否还有其他需要考虑的事情。

MySQL 死锁

评论


答:

0赞 Barmar 11/10/2023 #1

创建一个包含所需 ID 的临时表。然后你可以加入它,它应该只锁定这些行。

CREATE TEMPORARY TABLE temp_ids AS
SELECT id
FROM table
WHERE id % 4 = @y;

UPDATE table AS t
JOIN temp_ids as i ON t.id = i.id
SET t.data = @x;

如果您使用子查询或 CTE 联接,我认为它不会起作用,因为我怀疑这会在组合查询期间保持表锁定。

评论

0赞 Ecuador 11/10/2023
是的,我不认为可以通过单个查询来完成。我想我会选择一张临时桌子,它相当“干净”,而且似乎表现良好。