目次
トランザクションと MVCC の原則
同じデータを同時に操作する異なるトランザクションによって引き起こされる問題
LBCC はデータ損失を解決します
MVCC はデータ損失を解決します
InnoDB の MVCC 実装ロジック
書き込み-読み取り システムのパフォーマンスを向上させるために、操作は同時に実行されます。
ホームページ データベース SQL MySQL トランザクションと MVCC によって達成される分離レベルについて話しましょう

MySQL トランザクションと MVCC によって達成される分離レベルについて話しましょう

Jan 26, 2022 pm 05:11 PM
sql

この記事では、MySQL トランザクションの分離レベルと MVCC による分離レベルの実装方法に関連するいくつかの問題について説明します。

MySQL トランザクションと MVCC によって達成される分離レベルについて話しましょう

#データベース トランザクションの概要

トランザクションの 4 つの主要な特徴 (ACID)

  1. 原子性: トランザクションの最小作業単位。すべてが成功したか、すべてが失敗したか。

  2. 一貫性: トランザクションの開始と終了後、データベースの整合性は破壊されません。

  3. 分離: 異なるトランザクションは相互に影響しません。4 つの分離レベルは、RU (コミットされていない読み取り) と RC (コミットされた読み取り)、RR (反復可能読み取り) です。 )、SERIALIZABLE (シリアル化)。

  4. 耐久性 (耐久性): トランザクションが送信された後のデータへの変更は永続的であり、システムに障害が発生した場合でも失われることはありません。

トランザクションの分離レベル

UnCommitted/RU

を再び読み取ります。

dirtyと呼ばれます。 reading では、あるトランザクションはコミットされていないデータを別のトランザクションから読み取ることができます。コミットされていないトランザクションはロールバックされる可能性があるため、この分離レベルは最も安全性が低くなります。

Read Committed/RC

Non-repeatable read とも呼ばれる、トランザクションが別のトランザクションを読み取りました。送信された変更されたデータにより、一貫性のない結果が生じます。現在のトランザクションの異なる時点で同じデータを読み取ることによって取得されます。

たとえば、次の例では、SessionA がトランザクション中に異なるデータを 2 回クエリしていることがわかります。その理由は、現在の分離レベルが RC であり、セッション A のトランザクションはセッション B によって送信された最新データを読み取ることができるためです。

#発生時刻セッション Aセッション B12select * from user where id=1;(张三)34select * from user where id =1 ;(李思)ユーザー セット名 = ' Wang Er' を更新where id=1;(デフォルトの暗黙的トランザクションコミット)select * from user where id=1;(Wang Er)##Repeatable Read/RR
begin;

update user set name='李思' where id=1; (デフォルトの暗黙的コミットトランザクション)

5

6

ファントム読み取り とも呼ばれるトランザクション読み取りは、他のトランザクションによって送信されたデータですが、RR 分離レベルでは、このデータの現在の読み取りは 1 回しか読み取ることができません。現在のトランザクションでは、何度読み取られても、データは依然として、そのトランザクションに対して読み取られた値です。最初の読み取り後に他のトランザクションがこのデータを変更して送信するため、変更されません。したがって、読み出されるデータが必ずしも最新のデータであるとは限らず、ファントムリードともなります。

例: セッション A で初めてデータが読み取られるとき、送信されたデータを変更する後続のトランザクションは、セッション A によって読み取られるデータ値に影響を与えません。これは

繰り返し読める読書 です。

#発生時刻

セッション Aセッション Bbegin;select * from user where id=1;(张三)update user set name='李思' where id=1; (デフォルトの暗黙的トランザクション送信)select * from user where id =1 ;(Zhang San)##5ユーザー セット名 = ' Wang Er' を更新where id=1; (デフォルトの暗黙的なトランザクション送信)6
1
2
3
4


select * from user where id=1;(Zhang San)
#シリアル化可能
データベースの読み取りまたは書き込み操作はすべてシリアル行実行であり、現在の分離レベルは同時実行のみをサポートしています。すべての操作はキューの実行を必要とします。したがって、この分離レベルにあるすべてのデータは最も安定していますが、パフォーマンスも最悪になります。データベースのロック実装は、この分離レベルのより粒度が小さいバージョンです。

#発生時刻

セッション A

セッション B
1 begin;
2
#begin;
3
ユーザー セット名を更新='李四' where id=1;
4 select * from user where id=1;(待て、待て)
5
コミット;
6 選択* id=1 のユーザーから;(李思)

トランザクションと MVCC の原則

同じデータを同時に操作する異なるトランザクションによって引き起こされる問題

例:

##1begin;##23456現金で 100 元を引き出し、残高は 900 元に修正されます89 ##トランザクションのコミット (残高=1100) 900)
#発生時間 セッションA セッションB


begin;

残高確認 = 1,000 元
残高確認 = 1,000 元
##入金額は 100 元で、修正残高は 1100 元です

トランザクションをコミット (残高=1100)

#発生時刻##1開始;##開始;お問い合わせ残高 = 1,000 元お問い合わせ残高 = 1,000 元入金額は 100 元、修正残高は 1100 元です現金 100 元を引き出し、残高は 900 元に修正されます取引を送信 (残高 = 1100) ##9

上記の 2 つの状況は、複数のトランザクションが 1 つのデータに対して同時に動作する場合に発生する可能性がある問題で、特定のトランザクションの動作が上書きされ、データが失われる可能性があります。

LBCC はデータ損失を解決します

LBCC、ロックベースの同時実行制御。

ロック メカニズムを使用すると、現在のトランザクションがデータを変更する必要がある場合、現在のトランザクションはロックされます。現在のデータを同時に変更できるのは 1 つのトランザクションだけであり、他のトランザクションは待機する必要があります。ロックを解除するための操作を行います。

MVCC はデータ損失を解決します

MVCC、マルチバージョン同時実行制御、マルチバージョン同時実行制御。

バージョンを使用して同時実行状況でのデータの問題を制御します。トランザクション B がアカウントの変更を開始し、トランザクションが送信されないとき、トランザクション A がアカウント残高を読み取る必要がある場合、トランザクション B は次の時点で読み取られます。操作の前に口座残高のコピー データを変更しますが、トランザクション A が口座残高データを変更する必要がある場合、トランザクション B がトランザクションをコミットするまで待つ必要があります。

MVCC を使用すると、データをロックせずにデータベースを読み取り、ロックせずに通常の SELECT リクエストを実行できるようになり、データベースの同時処理能力が向上します。 MVCC の助けを借りて、データベースは READ COMMITTED や REPEATABLE READ などの分離レベルを実装できます。ユーザーは現在のデータの前または以前の履歴バージョンを表示して、ACID の I 機能 (分離) を確保できます。

InnoDB の MVCC 実装ロジック

InnoDB ストレージ エンジンによって保存される MVCC データ

InnoDB の MVCC は、各行の非表示列が実装された後に 2 つのレコードを保存します。 行を保存するトランザクション ID (DB_TRX_ID)、および行 を保存するロールバック ポインター (DB_ROLL_PT)。新しいトランザクションが開始されるたびに、新しいトランザクション ID が自動的に増加します。トランザクションの開始時に、トランザクション ID は、現在のトランザクションの影響を受ける行トランザクション ID に配置されます。クエリを実行する場合、現在のトランザクション ID と各行に記録されているトランザクション ID を比較する必要があります。

REPEATABLE READ 分離レベルで MVCC がどのように動作するかを見てみましょう。

SELECT

InnoDB は、次の 2 つの条件に従ってレコードの各行をチェックします。

  1. InnoDB はバージョンのみを検索します。現在のものよりも前のデータ行のトランザクション バージョン (つまり、行のトランザクション番号が現在のトランザクションのトランザクション番号以下であること)。これにより、トランザクションによって読み取られる行が以前にすでに存在していることが保証されます。トランザクションが開始されるか、トランザクション自体によって挿入または変更された。

  2. 削除された行は、トランザクション ID とトランザクションを読み取る前の状態のバージョンによって判断する必要があり、上記 2 つの条件を満たすレコードのみがクエリ結果として返されます。 。

INSERT

InnoDB は、新しく挿入された各行の行バージョン番号として現在のトランザクション番号を保存します。

DELETE

InnoDB は、削除された各行の行削除 ID として現在のトランザクション番号を保存します。

UPDATE

InnoDB は、新しいレコード行を挿入し、現在のトランザクション番号を行のバージョン番号として保存し、現在のトランザクション番号を元の行に行削除識別子。

ほとんどの読み取り操作をロックせずに実行できるように、これら 2 つの追加トランザクション番号を保存します。この設計により、データ読み取り操作が非常にシンプルになり、パフォーマンスが非常に向上し、また、規格を満たす行のみが確実に読み取られるようになります。欠点は、レコードの各行に追加の記憶域スペース、より多くの行チェック、および追加のメンテナンス作業が必要になることです。

MVCC は、REPEATABLE READ と READ COMMITIED の 2 つの分離レベルでのみ機能します。 READ UNCOMMITIED は、現在のトランザクション バージョンに準拠するデータ行ではなく、常に最新のデータ行を読み取るため、他の 2 つの分離レベルは MVCC と互換性がありません。 SERIALIZABLE は、読み取られたすべての行をロックします。

mysql での MVCC の実装は、アンドゥ ログと読み取りビューに依存しています。

アンドゥ ログ

さまざまな動作に応じて、アンドゥ ログは アンドゥ ログの挿入アンドゥ ログの更新#の 2 つのタイプに分類されます。

  • ##insert undo log:

# 挿入操作のみが記録されるため、挿入操作中に生成される元に戻すログ現在のトランザクション自体の場合、このレコードは他のトランザクションには表示されないため、トランザクションがコミットされた後、パージ操作を実行せずに挿入取り消しログを直接削除できます。

パージの主なタスクは、データベース内で del マークが付けられたデータを削除することです。さらに、元に戻すページもバッチでリサイクルします。

最初のデータベース挿入時のデータの状態:

  • 更新取り消しログ:

    更新または削除操作中に生成された取り消しログ。既存のレコードに影響を与えるため、MVCC メカニズムを提供するために、更新取り消しログはトランザクションの送信時に削除できません。代わりに、トランザクションの送信時に履歴リストに配置され、パージ スレッドが実行されるのを待ちます。最後の削除操作。

    データが初めて変更されるとき:

別のトランザクションが現在のデータを 2 回目に変更するとき:

同時トランザクション操作中にそれぞれの UNDO ログを書き込むときに競合が発生しないようにするために、InnoDB はロールバック セグメントを使用して同時書き込みと UNDO ログの永続性を維持します。ロールバック セグメントは、実際には Undo ファイルを整理する方法です。

読むビュー

RU(READ UNCOMMITTED) 分離レベルの場合、すべてのトランザクションはデータベースの最新の値を直接読み取ることができ、SERIALIZABLE 分離レベルの場合、すべてのリクエストはロックされ、同期的に実行されます。したがって、これら 2 つのケースでは、Read View のバージョン管理を使用する必要はありません。

RC(READ COMMITTED) および RR(REPEATABLE READ) の場合、分離レベルは上記のバージョン管理によって実装されます。 2 つの分離セクターの下での中心的な処理ロジックは、すべてのバージョンのうちのどのバージョンが現在のトランザクションに表示されるかを決定することです。この問題を解決するために、InnoDB は ReadView デザインをデザインに追加しました。ReadView には主に現在のシステム内のアクティブな読み取りおよび書き込みトランザクションが含まれており、それらのトランザクション ID をリストに入れます。 . 、このリストに m_ids という名前を付けます。

クエリ時にバージョンチェーンデータが表示されるかどうかの判定ロジック:

  • アクセスされたバージョンの trx_id 属性値が m_ids 内の最小のトランザクション ID より小さい場合このバージョンのトランザクションは ReadView を生成する前にコミットされているため、現在のトランザクションからこのバージョンにアクセスできることを示します。

  • アクセスされたバージョンの trx_id 属性値が m_ids リスト内の最大のトランザクション ID より大きい場合、このバージョンを生成したトランザクションが ReadView の生成後に生成されたことを示します。したがって、このバージョンは現在のトランザクション アクセスでは使用できません。

  • アクセスされたバージョンの trx_id 属性値が m_ids リスト内の最大のトランザクション ID と最小のトランザクション ID の間にある場合は、trx_id 属性値がm_ids リスト。そうである場合は、ReadView の作成時にこのバージョンを生成したトランザクションがまだアクティブであり、このバージョンにアクセスできないことを意味します。そうでない場合は、ReadView の作成時にこのバージョンを生成したトランザクションがコミットされたことを意味します、このバージョンにアクセスできます。

例:

分離レベルでの READ COMMITTED ReadView

データを読み取るたびに、すべてがReadView (m_ids リスト)

セッションA セッションB
2
#3
4
5
6
8

取引をキャンセル (残高は 1000 元に回復) )
##T1 begin;T2T3#T4##...UPDATE ユーザー SET name = 'Messi' WHERE id = 1;SELECT * FROM user where id = 1;#コミット;#UPDATE ユーザー セット名 = 'Neymar' WHERE id = 1;##T8 #SELECT * FROM user where id = 1;##UPDATE ユーザー セット名 = 'Dybala' WHERE id = 1;T10#SELECT * FROM user where id = 1;

これは、上記の状況における ReadView の分析です。

時点 T5 での SELECT ステートメント:

現時点でのバージョン チェーン:

This SELECT 文を実行すると現在のデータバージョンチェーンは上記の通り 現在のトランザクション 777 とトランザクション 888 が送信されていないため、この時点でアクティブなトランザクションの ReadView のリスト m_ids: [777, 888]、したがって、クエリ ステートメントは、現在のバージョン チェーン内の m_ids 未満の最大のバージョン データに基づきます。つまり、Mbappe がクエリされます。

時点 T8 の SELECT ステートメント:

現時点でのバージョン チェーンの状況:

この時点で SELECT ステートメントが実行されます。現在のトランザクション 777 は送信され、トランザクション 888 は送信されていないため、チェーンは上記のとおりです。したがって、この時点でアクティブなトランザクションの ReadView のリスト m_ids: [888] であるため、クエリ ステートメントは m_ids の最大バージョン データよりも小さいチェーンの現在のバージョンに基づきます。つまり、メッシがクエリされます。

時点 T11 の SELECT ステートメント:

現時点でのバージョン チェーン情報:

この時点で SELECT ステートメントが実行され、現在のデータ バージョン チェーンは上記の通りです。現在のトランザクション 777 とトランザクション 888 が送信されているため、この時点でアクティブなトランザクションの ReadView リストは空であるため、クエリ ステートメントは現在のデータベースの最新データを直接クエリします。つまり、ディバラは尋問される。

概要: READ COMMITTED 分離レベルを使用するトランザクションは、各クエリの開始時に独立した ReadView を生成します。

#REPEATABLE READ 分離レベルの ReadView

#トランザクション開始後の最初のデータ読み取り時に ReadView (m_ids リスト) を生成します

Time トランザクション 777 トランザクション 888 トランザクション 999



##開始;
begin;
UPDATE ユーザー SET 名 = 'CR7' WHERE ID = 1;



T5

T6

##T7



T9


#コミット;
##T11

#時間T1begin;開始;#T3UPDATE ユーザー セット名 = 'CR7' WHERE ID = 1;##T4...T5コミット;UPDATE ユーザー SET name = 'Neymar' WHERE id = 1;#T8T9UPDATE user SET名前 = 'ディバラ' WHERE id = 1;T10コミット;## SELECT * FROM user where id = 1;m_ids の内容は [777,888] であるため、ReadView の表示可能なバージョンに基づいてクエリされるデータは Mbappe です。
トランザクション 777 トランザクション 888 #トランザクション 999


T2

開始;




UPDATE ユーザー SET name = 'Messi' WHERE id = 1;
##SELECT * FROM user where id = 1; T6
##T7



SELECT * FROM user where id = 1;




##T11


#SELECT ステートメント (時点 T5):
現在のバージョン チェーン:
A ReadView は、時点 T5 で生成されます。 select ステートメントが現在実行されています。この時点で、

時点 T8 の SELECT ステートメント:

現在のバージョン チェーン:

現在のトランザクション 999 トランザクション。 ReadView は時点 T5 で生成されているため、ReadView は現在のトランザクションで 1 回だけ生成されるため、T5 の m_id はこの時点でもまだ使用されています: [777,999]、つまりこの時点のクエリ データまだムバッペだ。

時点 T11 の SELECT ステートメント:

現在のバージョン チェーン:

この時点の状況は T8 とまったく同じです。 ReadView は時点 T5 で生成されているため、ReadView は現在のトランザクションで 1 回だけ生成されるため、T5 の m_id はこの時点でもまだ使用されています: [777,999]、つまりこの時点のクエリ データまだムバッペだ。

MVCC の概要:

いわゆる MVCC (Multi-Version Concurrency Control、マルチバージョン同時実行制御) とは、

の使用を指します。 READ COMMITTDREPEATABLE READ

これら 2 つの分離レベルのトランザクションは、通常の SEELCT 操作の実行時に記録されたバージョン チェーンにアクセスするため、
読み取り-書き込み

書き込み-読み取り システムのパフォーマンスを向上させるために、操作は同時に実行されます。

推奨学習: mysql ビデオ チュートリアル

以上がMySQL トランザクションと MVCC によって達成される分離レベルについて話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Hibernate フレームワークにおける HQL と SQL の違いは何ですか? Hibernate フレームワークにおける HQL と SQL の違いは何ですか? Apr 17, 2024 pm 02:57 PM

HQL と SQL は Hibernate フレームワークで比較されます。HQL (1. オブジェクト指向構文、2. データベースに依存しないクエリ、3. タイプ セーフティ)、SQL はデータベースを直接操作します (1. データベースに依存しない標準、2. 複雑な実行可能ファイル)。クエリとデータ操作)。

Oracle SQLでの除算演算の使用法 Oracle SQLでの除算演算の使用法 Mar 10, 2024 pm 03:06 PM

「OracleSQLでの除算演算の使用方法」 OracleSQLでは、除算演算は一般的な数学演算の1つです。データのクエリと処理中に、除算演算はフィールド間の比率を計算したり、特定の値間の論理関係を導出したりするのに役立ちます。この記事では、OracleSQL での除算演算の使用法を紹介し、具体的なコード例を示します。 1. OracleSQL における除算演算の 2 つの方法 OracleSQL では、除算演算を 2 つの異なる方法で実行できます。

Oracle と DB2 の SQL 構文の比較と相違点 Oracle と DB2 の SQL 構文の比較と相違点 Mar 11, 2024 pm 12:09 PM

Oracle と DB2 は一般的に使用される 2 つのリレーショナル データベース管理システムであり、それぞれに独自の SQL 構文と特性があります。この記事では、Oracle と DB2 の SQL 構文を比較し、相違点を示し、具体的なコード例を示します。データベース接続 Oracle では、次のステートメントを使用してデータベースに接続します: CONNECTusername/password@database DB2 では、データベースに接続するステートメントは次のとおりです: CONNECTTOdataba

MyBatis動的SQLタグのSetタグ機能の詳細説明 MyBatis動的SQLタグのSetタグ機能の詳細説明 Feb 26, 2024 pm 07:48 PM

MyBatis 動的 SQL タグの解釈: Set タグの使用法の詳細な説明 MyBatis は、豊富な動的 SQL タグを提供し、データベース操作ステートメントを柔軟に構築できる優れた永続層フレームワークです。このうち、Set タグは、UPDATE ステートメントで SET 句を生成するために使用され、更新操作でよく使用されます。この記事では、MyBatis での Set タグの使用法を詳細に説明し、特定のコード例を通じてその機能を示します。 SetタグとはMyBatiで使用するSetタグです。

SQL の ID 属性は何を意味しますか? SQL の ID 属性は何を意味しますか? Feb 19, 2024 am 11:24 AM

SQL における Identity とは何ですか? 具体的なコード例が必要です。SQL では、Identity は自動インクリメント数値の生成に使用される特別なデータ型です。多くの場合、テーブル内のデータの各行を一意に識別するために使用されます。 Identity 列は、各レコードが一意の識別子を持つようにするために、主キー列と組み合わせてよく使用されます。この記事では、Identity の使用方法といくつかの実用的なコード例について詳しく説明します。 Identity の基本的な使用方法は、テーブルを作成するときに Identity を使用することです。

SQL ステートメントを使用せずに Springboot+Mybatis-plus を実装して複数のテーブルを追加する方法 SQL ステートメントを使用せずに Springboot+Mybatis-plus を実装して複数のテーブルを追加する方法 Jun 02, 2023 am 11:07 AM

Springboot+Mybatis-plus が SQL ステートメントを使用して複数テーブルの追加操作を実行しない場合、私が遭遇した問題は、テスト環境で思考をシミュレートすることによって分解されます: パラメーターを含む BrandDTO オブジェクトを作成し、パラメーターをバックグラウンドに渡すことをシミュレートします。 Mybatis-plus で複数テーブルの操作を実行するのは非常に難しいことを理解してください。Mybatis-plus-join などのツールを使用しない場合は、対応する Mapper.xml ファイルを設定し、臭くて長い ResultMap を設定するだけです。対応する SQL ステートメントを記述します。この方法は面倒に見えますが、柔軟性が高く、次のことが可能です。

SQL の 5120 エラーを解決する方法 SQL の 5120 エラーを解決する方法 Mar 06, 2024 pm 04:33 PM

解決策: 1. ログインしているユーザーがデータベースにアクセスまたは操作するための十分な権限を持っているかどうかを確認し、ユーザーが正しい権限を持っているかどうかを確認します; 2. SQL Server サービスのアカウントに指定されたファイルまたはデータベースにアクセスする権限があるかどうかを確認します。 3. 指定されたデータベース ファイルが他のプロセスによって開かれているかロックされているかどうかを確認し、ファイルを閉じるか解放して、クエリを再実行します。管理者として試してください。Management Studio をなどとして実行します。

MySQL でデータの集計と統計に SQL ステートメントを使用するにはどうすればよいですか? MySQL でデータの集計と統計に SQL ステートメントを使用するにはどうすればよいですか? Dec 17, 2023 am 08:41 AM

MySQL でデータの集計と統計に SQL ステートメントを使用するにはどうすればよいですか?データの集計と統計は、データ分析と統計を実行する際の非常に重要な手順です。 MySQL は強力なリレーショナル データベース管理システムとして、データの集約と統計操作を簡単に実行できる豊富な集約機能と統計機能を提供します。この記事では、SQL ステートメントを使用して MySQL でデータの集計と統計を実行する方法を紹介し、具体的なコード例を示します。 1. カウントには COUNT 関数を使用します。COUNT 関数は最も一般的に使用されます。

See all articles