高いロック速度を実現するために、MySQL は
InnoDB
および
NDBCLUSTER
以外のすべてのストレージエンジンに
(ページロック、行ロック、カラムロックではなく)
テーブルロックを使用します。
InnoDB
テーブルの場合は、MySQL で
LOCK TABLES
によって明示的にテーブルをロックした場合のみテーブルロックが使用されます。InnoDB
は自動行レベルロックを使用してトランザクションの遮断を確実にするため、このストレージエンジンには、LOCK
TABLES
をまったく使用しません。
大きいテーブルには、テーブルロックの方が行ロックより適切ですが、欠点もあります。
テーブルロックにより、同時に多数のセッションがテーブルからの読み取りを行うことができますが、あるセッションがテーブルへの書き込みを行うときは、まず排他処理をする必要があります。更新中は、この特定のテーブルにアクセスしようとするほかのすべてのセッションは、更新が完了するまで待機する必要があります。
ディスクが満杯になり、あるセッションが続行に必要な空き領域ができるまで待機している場合などには、テーブルロックによって問題が発生します。この場合、問題のテーブルにアクセスしようとするほかのセッションもすべて、より多くのディスク領域が利用可能になるまで待機状態となります。
ただし、テーブルロックは次のシナリオには適していません。
あるセッションが実行に長時間かかる
SELECT
を発行します。
その後、別のセッションが同じテーブルに対して
UPDATE
を発行します。このセッションは
SELECT
が完了するまで待機する必要があります。
別のセッションが同じテーブルに対して別の
SELECT
ステートメントを発行します。UPDATE
は SELECT
より優先度が高いため、この
SELECT
は
UPDATE
が完了するまで待機する必要があります。その前に、最初の
SELECT
の完了を待つ必要もあります。
次のアイテムはテーブルロックによる競合を軽減または回避する方法を記述します。
SELECT
ステートメントの実行の高速化を試行する。これにはサマリテーブルの作成が必要な場合もあります。
--low-priority-updates
のオプションで
mysqld
を開始する。テーブルレベルロックだけを使用するストレージエンジン
(MyISAM
、MEMORY
、MERGE
)
の場合、これは、テーブルを更新 (変更)
するすべてのステートメントの優先度を
SELECT
ステートメントの優先度より低くします。この場合、前シナリオの
2 つめの
SELECT
ステートメントは
UPDATE
ステートメントの前に実行され、一番目の
SELECT
が完了するまで待機する必要はありません。
特定の接続からの更新すべてが低い優先度で実行されるように指定するには、SET
LOW_PRIORITY_UPDATES=1
ステートメントを使用します。Session System Variables
を参照してください。
特定の
INSERT
、UPDATE
、または
DELETE
ステートメントの優先度を低く設定するには、LOW_PRIORITY
属性を使用します。
特定の
SELECT
ステートメントの優先度を高く指定するには、HIGH_PRIORITY
属性を使用します。項8.2.8. 「SELECT
構文」
を参照してください。
max_write_lock_count
システム変数の値を低くして
mysqld
を開始し、MySQL にすべての
SELECT
ステートメント
(特定数をテーブルに挿入したあとに待機しているステートメント)
の優先度を一時的に引き上げさせます。これは、一定数の
WRITE
ロックの後に
READ
ロックを設定します。
SELECT
と組み合わせた
INSERT
に問題がある場合は、SELECT
ステートメントと
INSERT
ステートメントの同時サポートが可能な
MyISAM
テーブルを使用するように切り替えます。詳細は、項4.3.3. 「同時挿入」
を参照してください。
同じテーブル上で insert と delete
ステートメントの混在が多い場合、INSERT
DELAYED
が非常に役立つ可能性があります。項8.2.5.2. 「INSERT DELAYED
構文」
を参照してください。
SELECT
と
DELETE
ステートメントに問題がある場合、DELETE
に LIMIT
オプションを使用すると解決できる場合があります。項8.2.2. 「DELETE
構文」
を参照してください。
SELECT
ステートメントで
SQL_BUFFER_RESULT
を使用すると、テーブルロックの持続を短縮することができます。項8.2.8. 「SELECT
構文」
を参照してください。
単一クエリーを使用するために、mysys/thr_lock.c
でロックコードを変更できることもあります。この場合、write
ロックと read
ロックは同等の優先度を持ち、いくつかのアプリケーションにとって役立つものとなります。
次は MySQL におけるテーブルロックについてのヒントです。
更新と、同じテーブルの多くの行を調べるセレクトを混合しないかぎり、同時ユーザーは問題を引き起こしません。
シングルロックを使用してのアップデートはロックなしでのアップデートよりも速いため、LOCK
TABLES
を使用して速度を上げることができます。テーブルのコンテンツを別々のテーブルに分けるのも効果的です。
MySQL
でテーブルロック関連の問題が生じたとき、テーブルを
InnoDB
に変換することで性能向上を図ることができます。章 9. InnoDB
ストレージエンジン
を参照してください。