高速なロックスピードを実現するため、MySQL
InnoDB
以外の全てのテーブルロックを全てのストレージエンジンに使用します。
InnoDB
テーブルの場合は、MySQL
でLOCK
TABLES
によって明示的テーブルをロックした場合のみテーブルロックが使用されます。
InnoDB
は自動行レベルロックを使用してトランザクションの独立を確実にするため、これらのテーブル型には、LOCK
TABLES
をまったく使用しないように推奨します。
大きいテーブルには、ほとんどのアプリケーションでテーブルロックの方が行ロックより適切ですが、落とし穴もあります。
テーブルロックにより、同時に多数のスレッドがテーブルからの読み取りを行うことができますが、あるスレッドがテーブルへの書き込みを行うときは、まず排他処理をする必要があります。更新時は、特定のテーブルにアクセスしようとする他のすべてのスレッドが、更新の準備ができるまで待機します。
一般にテーブルの更新はテーブル検索より重要だと見なされるため、テーブルを更新するステートメントは優先度が高くなります。これにより、更新では特定のテーブルに対して重いSELECT
アクティビティが使用されるため、更新が
「資源枯渇」
にさらされないことが確実になります。
テーブルロックによって、ディスク容量がいっぱいのため、スレッドが待機するような問題が引き起こされます。またスレッドが処理される前に開きスペースを利用可能にする必要があります。この場合、問題テーブルにアクセスを求める全てのスレッドも、より多くのディスクスペースが利用可能になるまで待機中となります。
ただし、テーブルロックは以下のシナリオには適していません。
クライアントが実行に長時間かかる
SELECT
を使用します。
その後、別のクライアントが使用テーブルに対して
UPDATE
を使用する。
このクライアントは
SELECT
が完了するまで待機が必要になる。
別のクライアントが同一テーブルに対してさらに
SELECT
ステートメントを使用します。UPDATE
はSELECT
より優先度が高いため、この
SELECT
は
UPDATE
が完了するまで待機が必要になります。また、最初の
SELECT
の完了を待つ必要もあります。
以下のアイテムはテーブルロックによる競合を軽減または回避する方法を記述します。
SELECT
ステートメントの実行の高速化を試行する。これにはサマリテーブルの作成が必要な場合もあります。
--low-priority-updates
のオプションで
mysqldを開始する。これは、テーブルを更新(変更)するすべてのステートメントの優先度を
SELECT
ステートメントの優先度より低くします。
この場合、前シナリオの2つ目のSELECT
ステートメントはUPDATE
ステートメントの前に実行され、一番目のSELECT
が完了するまで待機する必要はありません。
SET
LOW_PRIORITY_UPDATES=1
ステートメントを使用すると、特定の接続からの更新すべてが低い優先度で実行されるように指定できます。項12.5.3. 「SET
構文」を参照してください。
LOW_PRIORITY
属性を使用して、特定のINSERT
、UPDATE
、または
DELETE
ステートメントの優先度を低く設定できます。
HIGH_PRIORITY
性を使用すると、特定の
SELECT
の重要度を高く指定できます。項12.2.7. 「SELECT
構文」を参照してください。
max_write_lock_count
システム変数の値を低くしてmysqldを開始し、MySQLに全てのSELECT
ステートメント(特定数をテーブルに挿入した後に待機しているステートメント)の優先度を一時的に引き上げさせます。これは、一定数のWRITE
ロックの後にREAD
ロックを設定します。
SELECT
と結合したINSERT
に問題がある場合は、SELECT
ステートメントとINSERT
ステートメントの同時サポートが可能になるため、新規の
MyISAM
テーブルを使用するように切り替えます。(詳しくは項6.3.3. 「同時挿入」をご確認ください。)
同じテーブル上で
insertとdeleteステートメントの混在が多い場合、INSERT
DELAYED
が非常に役立つ可能性があります。項12.2.4.2. 「INSERT DELAYED
構文」を参照してください。
SELECT
とDELETE
ステートメントに問題がある場合、DELETE
にLIMIT
オプションを使用すると解決できる場合があります。項12.2.1. 「DELETE
構文」を参照してください。
SELECT
ステートメントでSQL_BUFFER_RESULT
を使用すると、テーブルロックの持続を短縮することができます。項12.2.7. 「SELECT
構文」を参照してください。
単一クエリを使用するために、mysys/thr_lock.c
でロックコードを変更できることもあります。この場合、writeロックとreadロックは同等の優先度をもち、いくつかのアプリケーションにとって役立つものとなります。
以下はMySQLにおけるテーブルロックについてのヒントです。
更新と、同じテーブルの多くの行を調べるセレクトを混合しない限り、同時ユーザは問題を引き起こしません。
シングルロックをしようしてのアップデートはロックなしでのアップデートよりも速いため、LOCK
TABLES
を使用して速度を上げることができます。テーブルのコンテンツを別々のテーブルに分けるのも効果的です。
MySQLでテーブルロック関連の問題が生じたとき、テーブルをInnoDB
に変換することで性能向上を図ることができます。項13.5. 「InnoDB
ストレージ エンジン」を参照してください。
MySQL Enterprise. ロックの競合は性能を著しく低下させます。MySQL Network Monitoring and Advisory Service はこの問題を回避するための専門的なアドバイスを提供します。購読を希望する場合は、http://www-jp.mysql.com/products/enterprise/advisors.htmlを参照してください。