[英]Howto bulk update a InnoDB table without deadlocks?
I have two tables, one having a many-to-many relationship ( fooBarTable
with columns fooId
and barId
) and another InnoDB table fooCounterTable
with columns fooId
and counter
counting the occurences of fooId
in fooBarTable
. 我有两个表,一个具有多对多关系( fooBarTable
与列fooId
和barId
)和另一个InnoDB表fooCounterTable
与列fooId
和counter
计数fooId
中fooBarTable
。
When deleting all barId
's from fooBarTable
, I need to update the fooCounterTable
accordingly. 当从fooBarTable
删除所有barId
,我需要相应地更新fooCounterTable
。
The first thing I tried was this: 我尝试的第一件事是:
UPDATE fooCounterTable SET counter = counter - 1
WHERE fooId IN (SELECT fooId FROM fooBarTable WHERE barId = 42 ORDER BY fooId);
But I got this error: 但我得到了这个错误:
MySQL error (1205): Lock wait timeout exceeded; try restarting transaction
Updating the table when adding barId
's is working fine with this SQL statement: 添加barId
时更新表可以正常使用此SQL语句:
INSERT INTO `fooCounterTable` (fooId, counter) VALUES (42,1), (100,1), (123,1)
ON DUPLICATE KEY UPDATE counter = counter + 1;
So I thought I'd do the same thing when decreasing the counter, even if it looks stupid to insert 0-Values, which should never happen: 因此我认为在减少计数器时我会做同样的事情,即使插入0值看起来很愚蠢,这应该永远不会发生:
INSERT INTO `fooCounterTable` (SELECT fooId, 0 FROM fooBarTable WHERE barId = 42 ORDER BY fooId)
ON DUPLICATE KEY UPDATE counter = counter - 1;'
This seems to work fine in most cases, but sometimes I get a deadlock: 在大多数情况下,这似乎工作正常,但有时我会陷入僵局:
MySQL error (1213): Deadlock found when trying to get lock; try restarting transaction
So I read about deadlocks and found out about SELECT ... FOR UPDATE
and I tried this: 所以我读到了关于死锁的信息并发现了有关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;
which resulted in: 结果导致:
MySQL error (2014): commands out of sync
Can anyone tell me how to resolve my problem? 谁能告诉我如何解决我的问题?
Update 更新
The last error (2014) occured, because I did not use and free the SELECT statement's results before executing the UPDATE statement, which is mandatory. 最后一个错误(2014)发生了,因为在执行UPDATE语句之前我没有使用并释放SELECT语句的结果,这是必需的。 I fixed that and I got rid of error 2014, but I still have deadlocks (error 1205) from time to time and I don't understand, why. 我解决了这个问题,我摆脱了2014年的错误,但我仍然不时遇到死锁(错误1205),我不明白,为什么。
Do you know what fooID you have just deleted when firing this query? 你知道在解雇这个查询时你刚删除了什么fooID吗?
If so seems like this would work... 如果是这样似乎会起作用......
UPDATE fooCounterTable SET counter =
(SELECT count(*) FROM fooBarTable WHERE fooId = 42)
WHERE fooID = 42
I wonder if you really need that counter table tho. 我想知道你是否真的需要那个柜台。 If your indexes are set up properly there shouldn't be too much of a speed penalty to a more normalized approach. 如果您的索引设置正确,那么对于更规范化的方法,不应该有太多的速度惩罚。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.