繁体   English   中英

如何在没有死锁的情况下批量更新InnoDB表?

[英]Howto bulk update a InnoDB table without deadlocks?

我有两个表,一个具有多对多关系( fooBarTable与列fooIdbarId )和另一个InnoDB表fooCounterTable与列fooIdcounter计数fooIdfooBarTable

当从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时更新表可以正常使用此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),我不明白,为什么。

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

如果是这样似乎会起作用......

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM