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
構文」。
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.