【问题标题】:Howto bulk update a InnoDB table without deadlocks?如何在没有死锁的情况下批量更新 InnoDB 表?
【发布时间】:2013-01-28 13:16:11
【问题描述】:

我有两个表,一个具有多对多关系(fooBarTable 与列 fooIdbarId)和另一个 InnoDB 表 fooCounterTable 与列 fooIdcounter 计算出现次数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


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 您的查询是由fooId 过滤的,但我需要找到给定barId 的所有fooId。我需要fooCounterTable,因为fooBarTable 有十亿行,查询通常要求多达1000 个fooId 计数器。因此,出于效率原因,我预先计算了计数器。
    猜你喜欢
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 2020-07-12
    • 1970-01-01
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多