簡體   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