我有两个表,一个具有多对多关系(fooBarTable
与列fooId
和),另一个具有列的barId
InnoDB 表并计算 in 的出现。fooCounterTable
fooId
counter
fooId
fooBarTable
从 中删除所有barId
's 时fooBarTable
,我需要fooCounterTable
相应地更新。
我尝试的第一件事是:
UPDATE fooCounterTable SET counter = counter - 1
WHERE fooId IN (SELECT fooId FROM fooBarTable WHERE barId = 42 ORDER BY fooId);
但我得到了这个错误:
MySQL error (1205): Lock wait timeout exceeded; try restarting transaction
在添加barId
's 时更新表可以使用此 SQL 语句正常工作:
INSERT INTO `fooCounterTable` (fooId, counter) VALUES (42,1), (100,1), (123,1)
ON DUPLICATE KEY UPDATE counter = counter + 1;
所以我想在减少计数器时我会做同样的事情,即使插入 0 值看起来很愚蠢,这永远不会发生:
INSERT INTO `fooCounterTable` (SELECT fooId, 0 FROM fooBarTable WHERE barId = 42 ORDER BY fooId)
ON DUPLICATE KEY UPDATE counter = counter - 1;'
在大多数情况下,这似乎工作正常,但有时我会陷入僵局:
MySQL error (1213): Deadlock found when trying to get lock; try restarting transaction
因此,我阅读了有关死锁的信息并发现SELECT ... FOR UPDATE
并尝试了以下方法:
START TRANSACTION;
SELECT fooId FROM fooCounterTable
WHERE fooId IN (SELECT fooId FROM fooBarTable WHERE barId = 42 ORDER BY fooId) FOR UPDATE;
UPDATE fooCounterTable SET counter = counter - 1
WHERE fooId IN (SELECT fooId FROM fooBarTable WHERE barId = 42 ORDER BY fooId);
COMMIT;
这导致:
MySQL error (2014): commands out of sync
谁能告诉我如何解决我的问题?
更新
发生最后一个错误(2014),因为我在执行 UPDATE 语句之前没有使用和释放 SELECT 语句的结果,这是强制性的。我解决了这个问题,我摆脱了错误 2014,但我仍然不时出现死锁(错误 1205),我不明白,为什么。