私のアプリケーションでは、デッドロックの原因となる(異なるプロセスから)2つのクエリが時々発生します。これらのクエリのロックモードSとXのInnoDBデッドロック
クエリ#1
UPDATE tblA, tblB SET tblA.varcharfield=tblB.varcharfield WHERE tblA.varcharfield IS NULL AND [a few other conditions];
クエリ#2
INSERT INTO tmp_tbl SELECT * FROM tblA WHERE [various conditions];
これらの両方のテーブルが数百万行を持っているように、かなりの時間を要します。クエリ#2が実行されているときは、S
でtblA
がロックされているようです。クエリ#1にはX
のロックが必要です。これはS
ロック、クエリ#私はデッドロックを取得した時点で、最大30秒間待つ、と互換性がありませんので:
シリアル化の失敗:ロックを取得しようとしたときに1213デッドロックが見つかりました。私はin the documentation読んだに基づいて取引
を再起動してみてください、私はカップルのオプションを持っていると思う:
- がtblA.varcharfieldにインデックスを設定します。残念ながら、私は、これはvarchar(512)のフィールドを格納するために非常に大きなインデックスが必要になると思います。 (下記の編集を参照してください...これは機能しませんでした)
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
でロックを無効にしてください。私はこれの意味を理解していないし、破損したデータが心配です。私は現在、私のアプリケーションで明示的なトランザクションを使用していませんが、私はいつか将来的にはそうかもしれません。- 時間のかかるクエリを小さな断片に分割し、30秒のタイムアウトに達することなくMySQLでキューに入れて実行できるようにします。これは実際に問題の中心を修正するものではなく、私のデータベースサーバがビジー状態になって問題が再発することが懸念されます。
- クエリを何度もやり直してください...私が望んでいるオプションではありません。
どうすればよいですか?私が検討すべき別の方法がありますか?
EDIT:私はvarcharfieldにインデックスを設定しようとしたが、テーブルはまだロックしています。私は、部分が実際に実行されているときにロックが発生すると思われます。この問題を回避するための他の提案はありますか?
ありがとうございます。私はDarhazerが提案したようにインデックスを使用しようとしましたが、役に立たない。私は 'UPDATE'が' SELECT'を実行する前に実行しなければならないと思っています。他のアドバイスはありますか? – Brad
まだ問題がある場合は、 'show innodb status'、デッドロックのセクションを入れてください。 – ravnur
ありがとうございます。私はテーブルを明示的にロックすることで問題を解決しました。残念ながら、デッドロックは、NDAのために公開できないクエリの他の部分によって引き起こされているに違いないと思います。問題の質問の単純化は適切ではありませんでした。私はあなたの助けを借りて、この問題を解決することに感謝します。 – Brad