2

我有两个表,一个具有多对多关系(fooBarTable与列fooId和),另一个具有列的barIdInnoDB 表并计算 in 的出现。fooCounterTablefooIdcounterfooIdfooBarTable

从 中删除所有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),我不明白,为什么。

4

1 回答 1

0

你知道在触发这个查询时你刚刚删除了什么 fooID 吗?

如果是这样,这似乎可行...

UPDATE fooCounterTable SET counter = 
  (SELECT count(*) FROM fooBarTable WHERE fooId = 42) 
  WHERE fooID = 42

我想知道你是否真的需要那个柜台。如果您的索引设置正确,那么更规范化的方法不应该有太多的速度损失。

于 2013-01-28T22:09:43.247 回答