MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  テーブルロックの問題

8.11.2 テーブルロックの問題

InnoDB テーブルでは、複数のセッションとアプリケーションが互いに待機したり、不整合の結果を生成したりすることなく、同じテーブルに対して同時に読み取りや書き込みを実行できるように、行レベルロックを使用します。 このストレージエンジンでは、LOCK TABLES ステートメントは特別な保護を提供せず、代わりに並列性が低くなるため、この使用を避けてください。 自動の行レベルロックにより、これらのテーブルがもっとも重要なデータを格納するもっともビジーなデータベースに適合し、同時にテーブルのロックやロック解除が必要ないためアプリケーションロジックが簡単になります。 その結果、InnoDB ストレージエンジンが MySQL のデフォルトになります。

MySQL は InnoDB を除く、すべてのストレージエンジンに対して、テーブルロック (ページ、行、またはカラムロックの代わりに) を使用します。 ロック操作自体には、あまりオーバーヘッドがありません。 ただし、一度に 1 つのセッションしかテーブルに書き込むことができないため、これらのほかのストレージエンジンでの最高のパフォーマンスのため、頻繁にクエリーされ、めったに挿入または更新されないテーブルに対して主にそれらを使用します。

InnoDB を優先するパフォーマンスの考慮事項

テーブルを作成するために、InnoDB を使用するか、別のストレージエンジンを使用するかを選択する場合、テーブルロックの次の短所を考慮してください。

  • テーブルロックにより、多くのセッションを同時にテーブルから読み取ることができますが、セッションでテーブルに書き込む必要がある場合、まず排他的アクセスを取得する必要がありますが、これはまずほかのセッションがテーブルを処理し終わるのを待つ必要がある可能性があることを意味します。 更新中、この特定のテーブルにアクセスしようとするほかのすべてのセッションは、更新が完了するまで待機する必要があります。

  • ディスクがいっぱいで、セッションを続行するには空き領域が使用できるようになる必要があるため、セッションが待機している場合にテーブルロックによって問題が発生します。 この場合、問題のテーブルにアクセスしようとするすべてのセッションが、より多くのディスク領域が使用できるようになるまで待機状態になります。

  • 実行に長時間かかる SELECT ステートメントにより、その間ほかのセッションのテーブルの更新が妨げられ、ほかのセッションが遅くなり、応答していないように見えます。 セッションが更新のためにテーブルへの排他的アクセスを取得するのを待機している間、SELECT ステートメントを発行する他のセッションはその背後でキューに入れられるため、読取り専用セッションでも同時実行性が低下します。

ロックパフォーマンスの問題の回避

次の項目では、テーブルロックによって発生する競合を回避または軽減するいくつかの方法について説明します。

  • セットアップ時に CREATE TABLE ... ENGINE=INNODB を使用するか、既存のテーブルに対して ALTER TABLE ... ENGINE=INNODB を使用して、テーブルを InnoDB ストレージエンジンに切り替えることを考慮します。 このストレージエンジンの詳細については、第15章「InnoDB ストレージエンジンを参照してください。

  • テーブルをロックする時間が短くなるように、SELECT ステートメントを最適化して、実行を高速化します。 これを実行するには、いくつかのサマリーテーブルを作成する必要がある場合があります。

  • --low-priority-updatesmysqld を起動します。 テーブルレベルロックのみを使用するストレージエンジン (MyISAMMEMORY、および MERGE など) の場合、これにより、テーブルを更新 (変更) するすべてのステートメントに SELECT ステートメントより低い優先度を与えます。 この場合、先述のシナリオの 2 つめの SELECT ステートメントは UPDATE ステートメントの前に実行され、最初の SELECT の終了を待機しません。

  • 特定の接続で発行されたすべての更新を低い優先度で実行させるように指定するには、low_priority_updates サーバーシステム変数を 1 に等しく設定します。

  • 特定の INSERTUPDATE、または DELETE ステートメントに低い優先度を与えるには、LOW_PRIORITY 属性を使用します。

  • 特定の SELECT ステートメントに高い優先度を与えるには、HIGH_PRIORITY 属性を使用します。 セクション13.2.10「SELECT ステートメント」を参照してください。

  • max_write_lock_count システム変数に低い値を指定して mysqld を起動し、テーブルに対する特定の数の書込みロックが発生した後 (挿入操作など)、テーブルを待機しているすべての SELECT ステートメントの優先度を MySQL によって一時的に昇格させます。 これにより、特定の数の書込みロックの後に読取りロックが許可されます。

  • 組み合わされた SELECTDELETE ステートメントに問題がある場合、DELETE への LIMIT オプションが役立つことがあります。 セクション13.2.2「DELETE ステートメント」を参照してください。

  • SELECT ステートメントで SQL_BUFFER_RESULT を使用すると、テーブルロックの時間の短縮に役立つことがあります。 セクション13.2.10「SELECT ステートメント」を参照してください。

  • テーブルの内容を個別のテーブルに分割すると (クエリーを 1 つのテーブルのカラムに対して実行し、更新を別のテーブルのカラムに制限することによって)、役立つことがあります。

  • 単一のキューを使用するように、mysys/thr_lock.c のロックコードを変更できます。 この場合、書き込みロックと読み取りロックは同じ優先度を持ち、一部のアプリケーションに役立つことがあります。


関連キーワード:  テーブル, ロック, ステートメント, InnoDB, インデックス, セッション, ストレージ, エンジン, 実行, クエリー