ホームページ >データベース >mysql チュートリアル >mysql の分離レベルはどのように実装されていますか?

mysql の分離レベルはどのように実装されていますか?

王林
王林オリジナル
2020-06-28 09:35:532872ブラウズ

Mysql 分離レベルの実装方法: 分離レベルが非コミット読み取りの場合、すべての読み取りはロックされず、読み取られたデータは最新のデータであり、パフォーマンスが最高で、すべての書き込みは行レベルでロック、リリースされます。書いた後。分離レベルがシリアル化の場合、読み取りと書き込みの両方がロックされます。

mysql の分離レベルはどのように実装されていますか?

#分離レベル

(推奨チュートリアル:

mysql チュートリアル)# #データベーストランザクションには4つの分離レベルがあり、低から高まで、Read uncommitted、Read Committed、Repeatable Read、Serializableとなっており、各レベルでダーティリード、Non-Repeatable Read、ファントムリードの問題を1つずつ解決できます。 。

分離レベルの実装:

非コミット読み取り (RU: 読み取り非コミット):

RU レベルでは、すべてのデータトランザクションによって読み取られるデータは最新のデータです。これは、トランザクションが送信された後のデータ、またはトランザクション実行中のデータ (ロールバックされる可能性があります) である可能性があります。

分離レベルが RU の場合:

    すべての読み取りはロックされず、読み取られるデータは最新のデータであり、パフォーマンスは最高です。
  • すべての書き込みでは行レベルのロックが追加され、書き込み後に解放されます。
読み取りコミット (RC: 読み取りコミット):

MVCC テクノロジを使用して、各行に隠しフィールドを追加します (DB_TRX_ID:行の最後のトランザクションの ID、DB_ROLL_PTR: 現在の行の UNDO ログを指す、DB_ROW_ID: 行識別子、DELETE_BIT: 削除フラグ)。非ロック読み取り操作を実装します。

分離レベルが RC の場合:

    書き込み操作: 行レベルのロックを追加します。トランザクションが開始されると、変更レコードが UNDO ログに書き込まれ、データ行の非表示列 DATA_POLL_PTR にその行の UNDO レコードへのポインタが格納されます。
  • 読み取り操作: ロックなし。読み取り時に行が他のトランザクションによってロックされている場合は、非表示列の DATA_POLL_PTR ポインターをたどって、前の有効な履歴レコード (有効なレコード: このレコードは現在のトランザクションに表示され、DELETE_BIT=0) を見つけます。
反復可能読み取り (RR: 反復可能読み取り):

MVCC テクノロジーを使用して、ロックフリー読み取り操作を実装します。

分離レベルが RR の場合:

    書き込み操作: 行レベルのロックを追加します。トランザクションが開始されると、変更レコードが UNDO ログに書き込まれ、データ行の非表示列 DATA_POLL_PTR にその行の UNDO レコードへのポインタが格納されます。
  • 読み取り操作: ロックなし。読み取り時に行が他のトランザクションによってロックされている場合は、非表示列の DATA_POLL_PTR ポインターをたどって、前の有効な履歴レコード (有効なレコード: このレコードは現在のトランザクションに表示され、DELETE_BIT=0) を見つけます。
  • 上記のことから、実際、RC レベルと RR レベルでの操作は基本的に同じですが、違いは次の点にあります。現在の行レコードの可視性です。トランザクション (可視性: つまり、どのバージョンの行レコードがこのトランザクションに表示されるか)。データの RC レベルの可視性はデータの最新のレコードであり、データの RR 基本可視性はトランザクションの開始時のデータのレコードです。

(1) 行レコードの可視性 (read_view) の実装

innodb では、トランザクションを作成すると、現在のシステムでアクティブなトランザクションのリストが作成されます。コピー (read_view)、現在のトランザクションの開始時にまだコミットされていないトランザクションを保存します。これらのトランザクションの値は、現在のトランザクションには表示されません。

read_view には 2 つのキー値 up_limit_id があります (現在のコミットされていないトランザクションの最小バージョン番号 -1、up_limit_id より前のトランザクションは送信済み、up_limit_id 以降のトランザクションは送信できる、または送信できない)および low_limit_id (現在のシステムによってまだ割り当てられていない次のトランザクション ID は、これまでに発生した最大値 1 です。注: low_limit_id は、最大のアクティブなトランザクションの ID ではありません。)

注: 現在のトランザクションおよびコミット中のトランザクションは read_view にありません。

(2) RC レベルでも RR レベルでも、行レコードの可視性を判断するロジックは同じです。

トランザクションが undo で行レコードを読み取るとき、行レコードのバージョン番号 (DB_TRX_ID) が read_view:

1 と比較されます。DB_TRX_ID が up_limit_id より小さい場合、それは次のことを意味します。行 現在のトランザクションが開始される前にレコードがコミットされており、DELETE_BIT=0 の場合、行レコードは現在のトランザクションに表示されます。

2. DB_TRX_ID が low_limit_id より大きい場合は、行が記録されているトランザクションがこのトランザクションの作成後に開始されたことを意味するため、行レコードの現在の値は表示されません。


3. up_limit_id< = DB_TRX_ID <= low_limit_id の場合、DB_TRX_ID がアクティブなトランザクション チェーンにあるかどうかを確認します。存在する場合は非表示になり、そうでない場合は表示されます。


4. 上記の判定がすべて非表示の場合は、undo でその行の前の行レコードを読み込んで判定を続行します。

RC レベルのステートメント レベルのスナップショットと RR レベルのトランザクション レベルのスナップショットの違いは、実際には read_view の生成のタイミングによって実現されます。

RC レベルでステートメントを実行すると、元の read_view が最初に閉じられ、新しい read_view が再生成されます。 RR レベルの read_view は、トランザクションの開始時にのみ作成されます。したがって、RU レベルでは毎回最新のデータが取得されますが、RR レベルではトランザクションの開始時にデータが取得されます。

(3) 注意すべき点: 上記の可視性の判断では、ロジックは同じですが、実際の意味では違いがあります。

In 2 番目の場合RC レベルの場合、low_limit_id はステートメント実行時に発生した最大のトランザクション ID 1 であり、ステートメント実行時には low_limit_id を超えるトランザクションは存在しないと考えられるため、low_limit_id を超えるトランザクションは表示されません。の。

RR レベルの場合、low_limit_id は現在のトランザクションの開始時に発生した最大のトランザクション 1 です (現在のトランザクションの ID 1 とみなすこともできます。これは、現在のトランザクションが作成されるときに、現在のトランザクションの ID が最大です)、low_limit_id より大きいトランザクションはトランザクションの開始後に作成されるため、RR レベルでは認識されません。

3 番目のステップでは、RC レベルの場合、DB_TRX_ID がアクティブなリンク リストにない限り、DB_TRX_ID がトランザクション ID より大きいかどうかに関係なく、RC が表示されます。

RR レベルの場合、low_limit_id が現在のトランザクション ID 1 であるため、現在のトランザクションが作成される前に low_limit_id より小さいトランザクションが発生したと考えられるため、単純に DB_TRX_ID がトランザクション ID にあるかどうかを判断するだけで済みます。アクティブなリンクされたリスト。

シリアル化可能: 読み取りと書き込みの両方がロックされます

以上がmysql の分離レベルはどのように実装されていますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。