10bet网址
MySQL 5.6リファレンスマニュアル
下载本手册
PDF(美国Ltr)- 26.8 mb
PDF (A4)- 26.8 mb


14.2.11デッドロックの対処方法

このセクションは,セクション14.2.10 "デッドロックの検出とロルバック"に示したデッドロックに関する概念情報に基づいています。ここでは,デッドロックが最小限になるようにデータベース操作を編成する方法,およびアプリケーションで必要となる後続のエラー処理について説明します。

デッドロックは,トランザクションデータベースの古典的な問題ですが,特定のトランザクションをまったく実行できないほど発生頻度が高くなければ,危険ではありません。通常は,デッドロックが発生したためにトランザクションがロールバックされた場合に,それを再発行できる準備が常にできているようにアプリケーションを作成する必要があります。

InnoDBでは自動行レベルロックが使用されます。単一の行を挿入または削除するだけのトランザクションの場合でも,デッドロックが発生する可能性があります。その原因は,これらの操作が実際には原子的でないためです。これらの操作では自動的に,挿入または削除される行のインデックスレコード(複数の可能性あり)にロックが設定されます。

次の方法を使用すれば,デッドロックに対処し,発生の可能性を減らすことができます。

  • いでも,显示引擎innodb状态コマンドを発行して,最近のデッドロックの原因を特定してください。これは,デッドロックが回避されるようにアプリケションを調整する際に役立ます。

  • 頻繁にデッドロックの警告が発生することに懸念がある場合は,innodb_print_all_deadlocks構成オプションを有効にして,より広範囲にわたるデバッグ情報を収集してください。MySQLのエラログには,最近のデッドロックだけでなく,各デッドロックに関する情報が記録されます。デバッグが完了したら,このオプションを無効にします。

  • デッドロックが原因でトランザクションに失敗した場合に,そのトランザクションを再発行できるように常に準備しておきます。デッドロックは危険ではありません。再度試してください。

  • トランザクションが競合する可能性を低くするために,トランザクションのサイズを小さく,期間を短く保ってください。

  • トランザクションが競合する可能性を低くするために,関連する一連の変更を行なった直後にトランザクションをコミットしてください。特に、コミットされていないトランザクションを含む以及ンタラクティブなmysqlセッションは,長時間開いたままにしないでください。

  • ロック読み取り选择……更新または选择……共享模式锁定)を使用する場合は,读过承诺などの低い分離レベルを使用してみてください。

  • トランザクション内の複数のテーブルを変更する場合や,同じテーブル内のさまざまな行のセットを変更する場合は,毎回,これらの操作を一貫性のある順序で実行してください。その結果,トランザクションで明示的に定義されたキュ,が生成され,デッドロックは発生しません。たとえば,さまざまな場所で同様の插入更新,および删除ステートメントのシーケンスを複数回コーディングするのではなく,データベース操作をアプリケーション内の関数に編成したり,ストアドルーチンを呼び出したりします。

  • テブルに適切な。これにより,クエリーでスキャンする必要のあるインデックスレコード数が減少するため,ロックの設定も減少します。MySQLサバがクエリに最適であるとみなす解释选择を使用してください。

  • ロックの使用を減らしてください。古いスナップショットからのデタを返すために,选择を許可する余裕がある場合は,更新または共享模式锁定句を追加しないでください。同じトランザクション内の各一貫性読み取りでは,独自の新しいスナップショットから読み取られるため,读过承诺分離レベルを使用することが適切な方法です。

  • ほかに方法がなければ,テブルレベルロックを使用してトランザクションを直列化してください。InnoDBテブルなどのトランザクションテブルで锁表を使用する正しい方法は,(开始事务ではなく)SET autocommit = 0でトランザクションを開始し,そのあと锁表を実行し,打开表を呼び出す前にそのトランザクションを明示的にコミットすることです。たとえば,テブルt1に書き込み,テブルt2から読み取る必要がある場合は,次のように実行できます。

    设置自动提交= 0;锁表t1写,t2读,…...在这里对表t1和t2做一些事情……提交;打开表;

    テーブルレベルロックを使用すると,テーブルへの並列更新が抑制されるため,デッドロックが回避されますが,負荷の高いシステムで応答性が低くなるという犠牲が伴います。

  • トランザクションを直列化する別の方法は,単一行だけを含む補助セマフォテブルを作成することです。ほかのテブルにアクセスする前に,各トランザクションでその行を更新してください。これにより,すべてのトランザクションが直列方式で発生します。直列化ロックは行レベルロックであるため,この場合,InnoDBの邮箱ンスタントデッドロック検出アルゴリズムも機能することに注意してください。MySQLのテーブルレベルロックを使用してデッドロックを解決するには、タイムアウト方式を使用する必要があります。