mysql:15005
From: goto <goto <gotou1213@xxxxxxxxxx>>
Date: Tue, 1 Sep 2009 00:53:02 +0900
Subject: [mysql 15005] 1行も削除されないDELETE文によるロック
こんばんは。ごとうと申します。 INNODBで下の様な主キーが複合のテーブルに対して、 ・第1キーを指定して一括DELETE ・同じ第1キーで複数件INSERT という処理を1トランザクションで行おうとしています。 -- CREATE TABLE test ( a INT NOT NULL, b INT NOT NULL, PRIMARY KEY (a, b) ) TYPE = INNODB; BEGIN; DELETE FROM test WHERE a = 1; INSERT INTO test (a, b) VALUES (1, 1); INSERT INTO test (a, b) VALUES (1, 2); ... COMMIT; -- この処理が↓のような順番で2接続で同時に実行されたとき、デッドロックしました。 -- 接続1> BEGIN; 接続1> DELETE FROM test WHERE a = 1; <-- 該当行なし 接続2> BEGIN; 接続2> DELETE FROM test WHERE a = 2; <-- 該当行なし 接続2> INSERT INTO test (a, b) VALUES (2, 1); <-- ブロックされる 接続1> INSERT INTO test (a, b) VALUES (1, 1); <-- デッドロック ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction -- 詳しく調べたところ、上の両方のDELETEで1行も削除されなかったときだけ (テーブルが空だった場合など)デッドロックが発生するようでした。 接続1は a=1 のみ処理し、接続2は a=2 のみ処理しているので問題ないように思うのですが・・・ ひとまず、DELETEの前に SELECT 〜 FOR UPDATE で行が存在するかを確認するようにすると デッドロックはしなくなりましたが、上記のような「一括削除→複数挿入」の 処理をする場合、どのようにするのが一般的でしょうか? また、色々実験してみたところ、 ↓の様な、主キーが一つだけのテーブルでも同じ現象が発生しました。 -- CREATE TABLE test ( id INT NOT NULL, PRIMARY KEY (id) ) TYPE = INNODB; 接続1> BEGIN; 接続1> DELETE FROM test WHERE id = 1; <-- 該当行なし 接続2> BEGIN; 接続2> DELETE FROM test WHERE id = 2; <-- 該当行なし 接続2> INSERT INTO test VALUES (2); <-- ブロックされる 接続1> INSERT INTO test VALUES (1); <-- デッドロック ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction -- これも削除される行があればデッドロックはしなかったので、 DELETE文で削除される行がある場合は、その行のみロックされ、 削除される行が無い場合はそのテーブル全体へのINSERTがブロックされる ような気がするのですが、そういうものなのでしょうか? MySQLのバージョンは「5.0.51a」と「5.1.32」で試しています。 トランザクション隔離レベルは最初デフォルトの「REPEATABLE READ」で試していましたが、 「READ UNCOMMITTED」でも同じ結果になりました。 よろしくお願いします。
-> 15005 2009-09-01 00:53 [goto <gotou1213@xxxx] 1行も削除されないDELETE文によるロック 15006 2009-09-01 10:01 ┗[HIRATSUKA Sadao <hir] 15007 2009-09-01 22:42 ┗[<gotou1213@xxxxxxxxx]