MySQL のテーブルロックコードはデッドロックフリーです。
MySQL は、InnoDB テーブルと BDB テーブルを除くすべてのテーブル型にテーブルロックを使用して、非常に高速なロックを実現します。大型のテーブルの場合、ほとんどのアプリケーションで行ロックと比較してテーブルロックのほうがはるかに優れていますが、これには危険もあります。
InnoDB テーブルと BDB テーブルの場合は、MySQL で LOCK TABLES によって明示的テーブルをロックした場合のみテーブルロックが使用されます。
InnoDB は自動行レベルロックを使用し、BDB はページレベルロックを使用してトランザクションの独立を確実にするため、これらのテーブル型には、LOCK TABLES をまったく使用しないように推奨します。
MySQL バージョン 3.23.7 以降は、MyISAM テーブルへのレコードの挿入を、他のスレッドが同一テーブルから読み取りを行うのと同時に実行できるようになりました。現在のところ、挿入実行時にテーブルのレコード削除後のホールがない場合にのみ、この機能が使用可能になるため注意が必要です。すべてのホールに新規のデータが入力されると、同時挿入が自動的に再度可能になります。
テーブルロックにより、同時に多数のスレッドがテーブルからの読み取りを行うことができますが、あるスレッドがテーブルへの書き込みを行うときは、まず排他処理をする必要があります。更新時は、特定のテーブルにアクセスしようとする他のすべてのスレッドが、更新の準備ができるまで待機します。
一般にテーブルの更新は SELECT より重要だと見なされるため、テーブルを更新するステートメントはすべて、テーブルから情報を取り出すステートメントより優先度が高くなります。これにより、更新では特定のテーブルに対して大量の重いクエリが使用されるため、更新が '資源枯渇' にさらされないことが確実になります(これは、更新を実行するステートメントを LOW_PRIORITY とともに使用するか、SELECT ステートメントとともに HIGH_PRIORITY を使用することで変更できます)。
MySQL バージョン 3.23.7 以降は、max_write_lock_count 変数を使用して、テーブルに対する挿入が一定数行われた後に、MySQL によってテーブルの使用を待機している SELECT ステートメントのすべてに高い優先度を強制的に設定できるようになりました。
ただし、テーブルロックは以下のシナリオには適していません。
クライアントが実行に長時間かかる SELECT を使用する。
その後、別のクライアントが使用テーブルに対して UPDATE を使用する。このクライアントは SELECT が完了するまで待機が必要になる。
別のクライアントが同一テーブルに対してさらに SELECT ステートメントを使用する。UPDATE は SELECT より優先度が高いため、この SELECT は UPDATE が完了するまで待機が必要になる。また、最初の SELECT の完了を待つ必要もある。
full disk などによってスレッドが待機中の場合、そのテーブルへのアクセスが必要なすべてのスレッドが追加のディスク容量が使用可能になるまで待機状態に置かれる。
この問題に対応する解決策は以下のとおりです。
SELECT ステートメントの実行の高速化を試行する。これにはサマリテーブルの作成が必要な場合もある。
--low-priority-updates のオプションで mysqld を開始する。これは、テーブルを更新(変更)するすべてのステートメントの優先度を SELECT ステートメントの優先度より低くする。この場合、前のシナリオの最後の SELECT ステートメントが INSERT ステートメントより前に実行されることになる。
LOW_PRIORITY 属性を使用して、特定の INSERT、UPDATE、または DELETE ステートメントの優先度を低く設定できる。
max_write_lock_count の値を低くして mysqld を開始し、一定数の WRITE ロックの後に READ ロックを設定する。
SQL コマンド SET LOW_PRIORITY_UPDATES=1 を使用すると、特定のスレッドからの更新すべてが低い優先度で実行されるように指定できる。
See 項5.5.6. 「SET 構文」。
HIGH_PRIORITY 属性を使用すると、特定の SELECT の重要度を高く指定できる。 See 項6.4.1. 「SELECT 構文」。
SELECT と結合した INSERT に問題がある場合は、SELECT ステートメントと INSERT ステートメントの同時サポートが可能になるため、新規の MyISAM テーブルを使用するように切り替える。
INSERT ステートメントと SELECT ステートメントの混在が多い場合、INSERT の DELAYED 属性によって問題が解決される確率が高い。
See 項6.4.3. 「INSERT 構文」。
SELECT と DELETE に問題がある場合、DELETE に LIMIT オプションを使用すると解決できる場合がある。 See 項6.4.5. 「DELETE 構文」。