InnoDB
テーブルでは、複数のセッションとアプリケーションが互いに待機したり、不整合の結果を生成したりすることなく、同じテーブルに対して同時に読み取りや書き込みを実行できるように、行レベルロックを使用します。 このストレージエンジンでは、LOCK TABLES
ステートメントは特別な保護を提供せず、代わりに並列性が低くなるため、この使用を避けてください。 自動の行レベルロックにより、これらのテーブルがもっとも重要なデータを格納するもっともビジーなデータベースに適合し、同時にテーブルのロックやロック解除が必要ないためアプリケーションロジックが簡単になります。 その結果、InnoDB
ストレージエンジンが MySQL のデフォルトになります。
MySQL は InnoDB
を除く、すべてのストレージエンジンに対して、テーブルロック (ページ、行、またはカラムロックの代わりに) を使用します。 ロック操作自体には、あまりオーバーヘッドがありません。 ただし、一度に 1 つのセッションしかテーブルに書き込むことができないため、これらのほかのストレージエンジンでの最高のパフォーマンスのため、頻繁にクエリーされ、めったに挿入または更新されないテーブルに対して主にそれらを使用します。
テーブルを作成するために、InnoDB
を使用するか、別のストレージエンジンを使用するかを選択する場合、テーブルロックの次の短所を考慮してください。
テーブルロックにより、多くのセッションを同時にテーブルから読み取ることができますが、セッションでテーブルに書き込む必要がある場合、まず排他的アクセスを取得する必要がありますが、これはまずほかのセッションがテーブルを処理し終わるのを待つ必要がある可能性があることを意味します。 更新中、この特定のテーブルにアクセスしようとするほかのすべてのセッションは、更新が完了するまで待機する必要があります。
ディスクがいっぱいで、セッションを続行するには空き領域が使用できるようになる必要があるため、セッションが待機している場合にテーブルロックによって問題が発生します。 この場合、問題のテーブルにアクセスしようとするすべてのセッションが、より多くのディスク領域が使用できるようになるまで待機状態になります。
実行に長時間かかる
SELECT
ステートメントにより、その間ほかのセッションのテーブルの更新が妨げられ、ほかのセッションが遅くなり、応答していないように見えます。 セッションが更新のためにテーブルへの排他的アクセスを取得するのを待機している間、SELECT
ステートメントを発行する他のセッションはその背後でキューに入れられるため、読取り専用セッションでも同時実行性が低下します。
次の項目では、テーブルロックによって発生する競合を回避または軽減するいくつかの方法について説明します。
セットアップ時に
CREATE TABLE ... ENGINE=INNODB
を使用するか、既存のテーブルに対してALTER TABLE ... ENGINE=INNODB
を使用して、テーブルをInnoDB
ストレージエンジンに切り替えることを考慮します。 このストレージエンジンの詳細については、第15章「InnoDB ストレージエンジン」を参照してください。テーブルをロックする時間が短くなるように、
SELECT
ステートメントを最適化して、実行を高速化します。 これを実行するには、いくつかのサマリーテーブルを作成する必要がある場合があります。--low-priority-updates
で mysqld を起動します。 テーブルレベルロックのみを使用するストレージエンジン (MyISAM
、MEMORY
、およびMERGE
など) の場合、これにより、テーブルを更新 (変更) するすべてのステートメントにSELECT
ステートメントより低い優先度を与えます。 この場合、先述のシナリオの 2 つめのSELECT
ステートメントはUPDATE
ステートメントの前に実行され、最初のSELECT
の終了を待機しません。特定の接続で発行されたすべての更新を低い優先度で実行させるように指定するには、
low_priority_updates
サーバーシステム変数を 1 に等しく設定します。特定の
INSERT
、UPDATE
、またはDELETE
ステートメントに低い優先度を与えるには、LOW_PRIORITY
属性を使用します。特定の
SELECT
ステートメントに高い優先度を与えるには、HIGH_PRIORITY
属性を使用します。 セクション13.2.10「SELECT ステートメント」を参照してください。max_write_lock_count
システム変数に低い値を指定して mysqld を起動し、テーブルに対する特定の数の書込みロックが発生した後 (挿入操作など)、テーブルを待機しているすべてのSELECT
ステートメントの優先度を MySQL によって一時的に昇格させます。 これにより、特定の数の書込みロックの後に読取りロックが許可されます。組み合わされた
SELECT
とDELETE
ステートメントに問題がある場合、DELETE
へのLIMIT
オプションが役立つことがあります。 セクション13.2.2「DELETE ステートメント」を参照してください。SELECT
ステートメントでSQL_BUFFER_RESULT
を使用すると、テーブルロックの時間の短縮に役立つことがあります。 セクション13.2.10「SELECT ステートメント」を参照してください。テーブルの内容を個別のテーブルに分割すると (クエリーを 1 つのテーブルのカラムに対して実行し、更新を別のテーブルのカラムに制限することによって)、役立つことがあります。
単一のキューを使用するように、
mysys/thr_lock.c
のロックコードを変更できます。 この場合、書き込みロックと読み取りロックは同じ優先度を持ち、一部のアプリケーションに役立つことがあります。