2

2 つのテーブルがあり、1 つは多対多の関係 (fooBarTablefooIdと) を持ち、もう 1 つは列を持つbarIdInnoDB テーブルで、 inの出現を数えます。fooCounterTablefooIdcounterfooIdfooBarTable

barIdからすべての を削除するときは、それに応じ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と、次の SQL ステートメントで正常に動作します。

INSERT INTO `fooCounterTable` (fooId, counter) VALUES (42,1), (100,1), (123,1)
    ON DUPLICATE KEY UPDATE counter = counter + 1;

だから私はカウンターを減らすときに同じことをするだろうと思った.

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

誰でも私の問題を解決する方法を教えてもらえますか?

アップデート

必須の UPDATE ステートメントを実行する前に SELECT ステートメントの結果を使用および解放しなかったため、最後のエラー (2014) が発生しました。私はそれを修正し、エラー 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 に答える