高速なロックスピードを実現するため、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を参照してください。
