MySQL ロックを理解するための記事

1 MySQL ロックの概要

1.1 ロックとは

ロックは、複数のプロセス間の同じ共有リソースへの同時アクセスを調整するためにコンピューターによって使用されるメカニズムです。MySQL では、データ アクセスやその他の機能の一貫性と有効性を確保するために、ロック メカニズムが実装されており、MySQL のロックはサーバー層またはストレージ エンジン層で実装されます。

1.2 ロックはどのような問題を解決するために使用されますか

ロックは、同時トランザクションのアクセス問題を解決するために使用されます。トランザクションが同時に実行されるときに発生する可能性のあるさまざまな問題はすでにわかっています。最大の困難は、一方ではデータベースへの同時アクセスを最大限に活用する必要があることです。一方で、特にあるトランザクションが読み取り操作を実行し、別のトランザクションが同時に変更操作を実行している場合には、各ユーザーが一貫した方法でデータの読み取りと変更を行えることを保証する必要があります。

1 つのトランザクションが読み取り操作を実行し、もう 1 つのトランザクションが変更操作を実行すると、前述したように、ダーティ リード、反復不可能な読み取り、ファントム リードなどの問題が発生する可能性があります。

ダーティ リード、反復不可能なリード、ファントム リードの問題を解決するにはどうすればよいでしょうか? 実際には、次の 2 つの解決策が考えられます。

オプション 1: 読み取り操作には MVCC、書き込み操作にはロック

このソリューションはパフォーマンスが優れていますが、古いバージョンのレコードを読み取る可能性があります

解決策 2: 読み取り操作と書き込み操作の両方をロックする

このソリューションのパフォーマンスは平均的ですが、最新のレコードを毎回読み取ることができます。たとえば、銀行業務のシナリオでは、セキュリティ要件が非常に高くなります。

2 ロックの分類

MySQL には多数のロックがあり、モードと粒度に応じて次のタイプに分類できます。

画像-20221003154244472

3 楽観的ロックと悲観的ロック

3.1 楽観的ロック

1.コンセプト

オプティミスティック ロックは、名前が示すとおり、非常に楽観的です。オプティミスティック ロックは、通常の状況ではデータが競合を引き起こすことはないと考えているため、データが更新のために送信されるときに競合が検出されます。

2. 実現する

楽観的ロックは、基本的なバージョン番号メカニズムによって実装されており、データ テーブルにバージョン フィールドが追加され、データを読み取るときにバージョンも一緒に読み取られます。データが更新されるたびに、バージョンフィールドの値 + 1 が加算されます。変更を送信する必要がある場合は、読み取り時のバージョン番号とデータベースの現在のバージョン番号を比較します。一貫性がある場合は、この期間中にこのレコードを変更した人がいないことを意味します。一貫性がない場合は、は変更されており、送信が失敗したことを意味します。

3. 適用可能なシナリオ

オプティミスティック ロックは、読み取り操作が多く書き込み操作が少ないシナリオに適しています。

3.2 悲観的ロック

1.コンセプト

悲観的ロックは楽観的ロックより悲観的であり、悲観的ロックは操作のたびにデータが変更されると考えているため、データを操作するたびにロックを追加します。

2. 実現する

悲観的ロックは、共有ロックと排他的ロックを通じて実装されます (これら 2 つのロックについては後で説明します)。

3. 適用可能なシナリオ

同時実行性が低く、書き込み操作が多く、読み取り操作が少ないシナリオに適用可能

4 共有排他ロック

4.1 共有ロック

1.コンセプト

共有ロックは読み取りロックとも呼ばれ、S ロックとも呼ばれます。トランザクションがデータに読み取りロックを追加すると、他のトランザクションはデータに読み取りロックのみを追加でき、書き込みロックは追加できません。

2. 実現する

共有ロックのロック方法: […共有モードでロック] を選択します。

画像-20221003172941494

画像-20221003173149274

4.2 排他ロック

1.コンセプト

排他的ロック (書き込みロック、略して X ロックとも呼ばれます)。トランザクションがデータに排他的ロックを追加すると、他のトランザクションはデータのクエリや変更を行うことができなくなります。

MySQL InnoDB エンジンは、デフォルトでは、更新、削除、および挿入を行うと、関連するデータに排他ロックを自動的に追加します。また、select ステートメントは、デフォルトではロック タイプを追加しません。

2. 実現する

排他ロックのロック方法:更新用に選択してください

画像-20221003173825780

画像-20221003173942828

5つの粒状ロック

5.1 グローバルロック

1.コンセプト

グローバル ロックは、名前からわかるように、MySQL データベース インスタンス全体をロックし、ロック期間中はデータベースの追加、削除、変更を行うことができません。

2. 実現する

MySQL はグローバル読み取りロックを追加する方法を提供します。コマンドは次のとおりです。Flush tables with read lock (FTWRL)

3. 適用可能なシナリオ

データベース データの完全バックアップ。グローバル ロックを使用できますが、他の場合には使用しないでください。

5.2 テーブルレベルのロック

1.コンセプト

テーブル レベルのロック。現在操作されているテーブルをロックします。MyISAM エンジンと InnoDB エンジンの両方がテーブル レベルのロックをサポートします。

MySQL には 2 種類のテーブル レベルのロックがあります。1 つはテーブル ロック、もう 1 つはメタデータ ロック (メタデータ ロック、MDL) です。

2. 実現する

テーブルロックの追加: テーブルの読み取り/書き込みをロックします。

画像-20221003175254955

画像-20221003175706554

テーブルのロックを解除します。

ステップ 1: ロックされたテーブルを見つける

プロセスリストを表示

画像-20221003180108421

ステップ 2: ロックされたテーブルを削除するプロセスを強制終了します。

kill 21;
kill 22;

ユーザーテーブルデータを再度更新します

画像-20221003180453415

普通に更新できる

5.3 ページレベルのロック

ページレベルのロックは、MySQL のロックの一種で、そのロック粒度は行レベルのロックとテーブルレベルのロックの間です。テーブルレベルのロックは高速ですが、競合が多く、行レベルのロックは競合が少ないですが、遅くなります。したがって、隣接するレコードのグループを一度にロックするために、妥協したページレベルのロックが採用されます。BDB エンジンはページレベルのロックをサポートします

5.4 行レベルのロック

1.コンセプト

行レベルのロックは MySQL で最も粒度の細かいロックであり、ロック競合の可能性は最も低くなりますが、ロックは遅くて高価です

MySQL では InnoDB エンジンのみが行ロックをサポートしており、他のエンジンはサポートしていません。

2. 実現する

MySQL では、行レベルのロックはインターロック レコードではなく、ロック インデックスです。MySQL は更新ステートメントと削除ステートメントを実行するときに行ロックを自動的に追加します。

画像-20221003181021358

画像-20221003181133774

6 インテントロック

1.コンセプト

インテンション ロックはテーブル ロックであり、行ロックとテーブル ロックの関係を調整するために、複数の粒度 (テーブル ロックと行ロック) のロックが共存します。

2.機能

トランザクション A に行ロックがある場合、MySQL はテーブルにインテント ロックを自動的に追加します。トランザクション B がテーブル全体に書き込みロックを適用したい場合、各行を走査してロックが存在するかどうかを判断する必要はありません。行ロックを行いますが、インテントロックが存在するかどうかを直接判断し、パフォーマンスを向上させます。

3. 互換性

インテント共有ロック (IS) インテント排他ロック (IX)
共有ロック 互換性がある 相互排他的
排他ロック 相互排他的 相互排他的

7 ギャップ プロ キー レコード ロック

1.コンセプト

レコード ロック、ギャップ ロック、隣接キー ロックはすべて排他ロックであり、レコード ロックの使用は排他ロックの導入と一致します。

7.1 レコードのロック

レコード ロックはブロックされたレコードであり、レコード ロックは行ロックとも呼ばれます。次に例を示します。

select * from user where id = 1 for update;

id=1 のレコードにレコード ロックを追加して、他のトランザクションが id=1 の行を挿入、更新、削除できないようにします。

7.2 ギャップロック

ギャップ ロックは非一意のインデックスに基づいており、インデックス レコードの範囲をロックします。ギャップ ロックは、この間隔内のすべてのデータだけでなく、間隔をロックするために使用されます。

select * from user where id < 10 for update;

つまり、間隔 [1, 10) 内のすべてのレコード行がロックされ、ID が 1、2、3、4、5、6、7、8、および 9 のすべてのデータ行の挿入がブロックされます。

画像-20221003182325290

画像-20221003182340884

7.3 プロキーロック

近接キーロックはレコードロックとギャップロックを組み合わせたもので、ブロック範囲にはインデックスレコードとインデックス間隔(左開きと右閉じの間隔)の両方が含まれます。キーロックの主な目的は、ファントムリード (Phantom Read) を回避することです。トランザクションの分離レベルが RC にダウングレードされた場合、キー ロックも失敗します。

各データ行の非一意インデックス列には一時キー ロックが適用されます。トランザクションがデータ行の一時キー ロックを保持すると、左オープンおよび右クローズの間隔でデータのセクションがロックされます。InnoDB の行レベルのロックはインデックスに基づいて実装されており、一時キー ロックは非一意のインデックス列にのみ関連しており、一時キー ロックは一意のインデックス列 (主キー列を含む) には存在しないことを強調する必要があります。

おすすめ

転載: blog.csdn.net/wgzblog/article/details/127281354