【发布时间】:2013-01-28 13:16:11
【问题描述】:
我有两个表,一个具有多对多关系(fooBarTable 与列 fooId 和 barId)和另一个 InnoDB 表 fooCounterTable 与列 fooId 和 counter 计算出现次数fooId 中的 fooBarTable。
从fooBarTable 中删除所有barId 时,我需要相应地更新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),我不明白,为什么。
【问题讨论】:
标签: mysql sql-update innodb deadlock