このセクションでは,内部ロック,つまり複数のセッションによるテーブル内容の競合を管理するために,MySQLサーバー自体の内部で実行されるロックについて説明します。この種類のロックは,完全にサーバーによって実行され,ほかのプログラムは関与しないため,内部です。ほかのプログラムによってMySQLファイルに対して実行されるロックについては,セクション8.10.5”外部ロック”を参照してください。
行レベルロック
MySQLはInnoDB
テーブルに行レベルロックを使用して,複数のセッションによる同時書き込みアクセスをサポートし,それらを複数ユーザー,高度な並列性,およびOLTPアプリケーションに適したものにします。
単一のInnoDB
テーブルに対する複数の同時書き込み操作の実行時のデッドロックを避けるには,トランザクションのあとの方にDMLステートメントがある場合でも,変更が予想される行のグループごとに,选择……更新
ステートメントを発行して,トランザクションの開始時に必要なロックを獲得します。トランザクションで複数のテーブルを変更またはロックする場合,各トランザクション内で,該当するステートメントを同じ順序で発行します。InnoDB
は自動的にデッドロック状況を検出し,影響のあるいずれかのトランザクションをロールバックするため,デッドロックは重大エラーを表すより,パフォーマンスに影響します。
行レベルロックの利点:
異なるセッションが異なる行にアクセスする場合,ロックの競合は少なくなります。
ロールバックする変更が少なくなります。
1つの行を長時間ロックできます。
テーブルレベルロック
MySQLは,MyISAM
、内存
,および合并
テーブルにテーブルレベルロックを使用して,一度に1つだけのセッションがそれらのテーブルを更新できるようにし,それらを読み取り専用,読み取りが大部分,または単一ユーザーのアプリケーションに適したものにします。
これらのストレージエンジンは,常にクエリーの最初に1回だけ必要なすべてのロックをリクエストし,常に同じ順序でテーブルをロックすることによって,デッドロックを回避します。このトレードオフは,この戦略では並列性が低くなることです。テーブルを変更したいほかのセッションは,現在のDMLステートメントが終了するまで待機する必要があります。
MySQLはテーブル書き込みロックを次のように許可します。
テーブルにロックがない場合,それを書き込みロックします。
そうでない場合,書き込みロックキューにロックリクエストを入れます。
MySQLはテーブル読み取りロックを次のように許可します。
テーブルに書き込みロックがない場合,それを読み取りロックします。
そうでない場合,読み取りロックキューにロックリクエストを入れます。
テーブルの更新は,テーブルの取得よりも高い優先度が与えられます。そのため,ロックが解放されると,ロックは書き込みロックキュー内のリクエストに使用できるようになり,次に読み取りロックキュー内のリクエストに使用できるようになります。これにより,テーブルに対して重い选择
アクティビティーがある場合でも,テーブルに対する更新が「不足」することはありません。ただし,テーブルに対して多くの更新がある場合,选择
ステートメントは更新がなくなるまで待機します。
読み取りと書き込みの優先度を変更する方法については,セクション8.10.2“テーブルロックの問題”を参照してください。
Table_locks_immediate
およびTable_locks_waited
ステータス変数をチェックすることでシステム上のテーブルロック競合を分析できます。これらは,テーブルロックのリクエストがすぐに許可された回数と待機する必要があった回数を示します。
mysql> SHOW STATUS LIKE 'Table%';+-----------------------+---------+ | Variable_name |值 | +-----------------------+---------+ | Table_locks_immediate | 1151552 | | Table_locks_waited | 15324年 | +-----------------------+---------+
MyISAM
ストレージエンジンでは,特定のテーブルのリーダーとライター間の競合を軽減するために,同時挿入をサポートしています。MyISAM
テーブルでデータファイルの途中に空きブロックがない場合,行は常にデータファイルの末尾に挿入されます。この場合,ロックなしでMyISAM
テーブルに対して同時插入
および选择
ステートメントを自由に組み合わせることができます。つまり,ほかのクライアントがMyISAM
テーブルから読み取ると同時に,それに行を挿入できます。テーブルの途中で行が削除されるか更新されると,隙間が発生します。隙間がある場合,同時挿入は無効にされますが,すべての隙間が新しいデータで埋められた場合は,自動的にふたたび有効にされます。この動作はconcurrent_insert
システム変数によって変更します。セクション8.10.3”同時挿入”を参照してください。
锁表
で明示的にテーブルロックを獲得する場合,读
ロックではなく阅读当地
ロックをリクエストして,テーブルをロックしている間に,ほかのセッションが同時挿入を実行できるようにできます。
同時挿入が可能でない場合に,テーブルreal_table
に対して多くの插入
および选择
操作を実行するには,一時テーブルtemp_table
に行を挿入し,定期的に一時テーブルからの行で実際のテーブルを更新します。これは次のコードで実行できます。
mysql> LOCK table real_table WRITE, temp_table WRITE;mysql> INSERT INTO real_table SELECT * FROM temp_table;mysql>删除temp_table;mysql >解锁表;
テーブルレベルロックの利点:
必要なメモリーが比較的少なくなります。
単一のロックだけが必要であるため,テーブルの大部分に対して使用する場合に高速です。
データの大部分に対して
集团
操作を頻繁に実行する場合や,テーブル全体を頻繁にスキャンする必要がある場合に高速です。
一般にテーブルロックは次の場合に適しています。
テーブルに対するほとんどのステートメントが読み取りです。
テーブルに対するステートメントが読み取りと書き込みの組み合わせであり,そのうち書き込みは1つのキーの読み取りでフェッチできる単一の行に対する更新または削除です。
更新tbl_name集列=价值在哪里unique_key_col=key_value;删除从tbl_name在哪里unique_key_col=key_value;
同時
插入
ステートメントとごく少数の更新
または删除
ステートメントと組み合わされた选择
。ライターを使用しない,テーブル全体への多くのスキャンまたは
集团
操作。