Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 27.1Mb
PDF (A4) - 27.1Mb
EPUB - 7.5Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


8.10.1 内部ロック方法

このセクションでは、内部ロック、つまり複数のセッションによるテーブル内容の競合を管理するために、MySQL サーバー自体の内部で実行されるロックについて説明します。この種類のロックは、完全にサーバーによって実行され、ほかのプログラムは関与しないため、内部です。ほかのプログラムによって MySQL ファイルに対して実行されるロックについては、セクション8.10.5「外部ロック」を参照してください。

行レベルロック

MySQL は InnoDB テーブルに行レベルロックを使用して、複数のセッションによる同時書き込みアクセスをサポートし、それらを複数ユーザー、高度な並列性、および OLTP アプリケーションに適したものにします。

単一の InnoDB テーブルに対する複数の同時書き込み操作の実行時のデッドロックを避けるには、トランザクションのあとの方に DML ステートメントがある場合でも、変更が予想される行のグループごとに、SELECT ... FOR UPDATE ステートメントを発行して、トランザクションの開始時に必要なロックを獲得します。トランザクションで複数のテーブルを変更またはロックする場合、各トランザクション内で、該当するステートメントを同じ順序で発行します。InnoDB は自動的にデッドロック状況を検出し、影響のあるいずれかのトランザクションをロールバックするため、デッドロックは重大エラーを表すより、パフォーマンスに影響します。

行レベルロックの利点:

  • 異なるセッションが異なる行にアクセスする場合、ロックの競合は少なくなります。

  • ロールバックする変更が少なくなります。

  • 1 つの行を長時間ロックできます。

テーブルレベルロック

MySQL は、MyISAMMEMORY、および MERGE テーブルにテーブルレベルロックを使用して、一度に 1 つだけのセッションがそれらのテーブルを更新できるようにし、それらを読み取り専用、読み取りが大部分、または単一ユーザーのアプリケーションに適したものにします。

これらのストレージエンジンは、常にクエリーの最初に 1 回だけ必要なすべてのロックをリクエストし、常に同じ順序でテーブルをロックすることによって、デッドロックを回避します。このトレードオフは、この戦略では並列性が低くなることです。テーブルを変更したいほかのセッションは、現在の DML ステートメントが終了するまで待機する必要があります。

MySQL はテーブル書き込みロックを次のように許可します。

  1. テーブルにロックがない場合、それを書き込みロックします。

  2. そうでない場合、書き込みロックキューにロックリクエストを入れます。

MySQL はテーブル読み取りロックを次のように許可します。

  1. テーブルに書き込みロックがない場合、それを読み取りロックします。

  2. そうでない場合、読み取りロックキューにロックリクエストを入れます。

テーブルの更新は、テーブルの取得よりも高い優先度が与えられます。そのため、ロックが解放されると、ロックは書き込みロックキュー内のリクエストに使用できるようになり、次に読み取りロックキュー内のリクエストに使用できるようになります。これにより、テーブルに対して重い SELECT アクティビティーがある場合でも、テーブルに対する更新が不足することはありません。ただし、テーブルに対して多くの更新がある場合、SELECT ステートメントは更新がなくなるまで待機します。

読み取りと書き込みの優先度を変更する方法については、セクション8.10.2「テーブルロックの問題」を参照してください。

Table_locks_immediate および Table_locks_waited ステータス変数をチェックすることでシステム上のテーブルロック競合を分析できます。これらは、テーブルロックのリクエストがすぐに許可された回数と待機する必要があった回数を示します。

mysql> SHOW STATUS LIKE 'Table%';
+-----------------------+---------+
| Variable_name         | Value   |
+-----------------------+---------+
| Table_locks_immediate | 1151552 |
| Table_locks_waited    | 15324   |
+-----------------------+---------+

MyISAM ストレージエンジンでは、特定のテーブルのリーダーとライター間の競合を軽減するために、同時挿入をサポートしています。MyISAM テーブルでデータファイルの途中に空きブロックがない場合、行は常にデータファイルの末尾に挿入されます。この場合、ロックなしで MyISAM テーブルに対して同時 INSERT および SELECT ステートメントを自由に組み合わせることができます。つまり、ほかのクライアントが MyISAM テーブルから読み取ると同時に、それに行を挿入できます。テーブルの途中で行が削除されるか更新されると、隙間が発生します。隙間がある場合、同時挿入は無効にされますが、すべての隙間が新しいデータで埋められた場合は、自動的にふたたび有効にされます。この動作は concurrent_insert システム変数によって変更します。セクション8.10.3「同時挿入」を参照してください。

LOCK TABLES で明示的にテーブルロックを獲得する場合、READ ロックではなく READ LOCAL ロックをリクエストして、テーブルをロックしている間に、ほかのセッションが同時挿入を実行できるようにできます。

同時挿入が可能でない場合に、テーブル real_table に対して多くの INSERT および SELECT 操作を実行するには、一時テーブル temp_table に行を挿入し、定期的に一時テーブルからの行で実際のテーブルを更新します。これは次のコードで実行できます。

mysql> LOCK TABLES real_table WRITE, temp_table WRITE;
mysql> INSERT INTO real_table SELECT * FROM temp_table;
mysql> DELETE FROM temp_table;
mysql> UNLOCK TABLES;

テーブルレベルロックの利点:

  • 必要なメモリーが比較的少なくなります。

  • 単一のロックだけが必要であるため、テーブルの大部分に対して使用する場合に高速です。

  • データの大部分に対して GROUP BY 操作を頻繁に実行する場合や、テーブル全体を頻繁にスキャンする必要がある場合に高速です。

一般にテーブルロックは次の場合に適しています。

  • テーブルに対するほとんどのステートメントが読み取りです。

  • テーブルに対するステートメントが読み取りと書き込みの組み合わせであり、そのうち書き込みは 1 つのキーの読み取りでフェッチできる単一の行に対する更新または削除です。

    UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;
    DELETE FROM tbl_name WHERE unique_key_col=key_value;
    
  • 同時 INSERT ステートメントとごく少数の UPDATE または DELETE ステートメントと組み合わされた SELECT

  • ライターを使用しない、テーブル全体への多くのスキャンまたは GROUP BY 操作。


User Comments
Sign Up Login You must be logged in to post a comment.