MySQL InnoDB トランザクション分離レベルには 4 つのレベルがあり、デフォルトは「REPEATABLE READ」です。
· 1) コミットされていない読み取り (READUNCOMMITTED)。別のトランザクションはデータを変更しましたが、まだコミットしていません。このトランザクションの SELECT は、これらのコミットされていないデータを読み取ります (ダーティ リード)( 最も低い分離レベル、高い同時実行パフォーマンス)。
· 2) 読み取り値を送信します (READCOMMITTED)。このトランザクションが読み取るのは、(他のトランザクションがコミットされた後の) 最新のデータです。問題は、同じトランザクション内で、同じ SELECT が (繰り返し読み取られることなく) 異なる結果を 2 回読み取ることです。反復不可能な読み取りとファントム読み取りの問題 (読み取り中の行のロック) が発生します
· 3)。同一トランザクション内では、SELECT の結果はトランザクション開始時の状態となるため、同一の SELECT 操作で読み取った結果は一致します。ただし、ファントムリーディング(後述)が発生します。ファントム読み取りが発生します (読み取られたすべての行はロックされます)。
· 4).シリアル化 (SERIALIZABLE)。読み取り操作は暗黙的に共有ロックを取得するため、異なるトランザクション間の相互排他 (ロック テーブル) が保証されます。
‘
4 つのレベルが徐々に強くなり、各レベルで問題が解決されます。
· 1) 汚い読書。別のトランザクションがデータを変更しましたが、まだコミットされていないため、このトランザクションの SELECT はコミットされていないデータを読み取ります。
· 2) 繰り返し読まないでください。ダーティ リードを解決した後、同じトランザクションの実行中に、別のトランザクションが新しいデータを送信したため、このトランザクションによって 2 回読み取られたデータの結果が不整合になることがわかります。
· 3)ファントムリーディング。これにより、非反復読み取りの問題が解決され、同じトランザクション内で query の結果がトランザクション開始時の状態 (一貫性) になることが保証されます。ただし、別のトランザクションが同時に新しいデータを送信し、このトランザクションが再び更新されると、これらの新しいデータを発見して「驚き」、以前に読み取られたデータが「幽霊」であるように見えます。 具体的には: 1). ダーティ リード まずダーティ ページとダーティ データを区別します ダーティ ページはメモリ バッファです プール内で変更されたページは、まだ変更されていません更新はハードディスクにフラッシュされましたが、REDO ログに書き込まれました。バッファ プール内のページの読み取りと変更は正常であり、フラッシュにより効率が向上します。ダーティ データは、トランザクションがバッファ プール内の行レコードを変更したが、まだ送信していないことを意味します。 ! ! 、このときにバッファープール内のコミットされていない行データが読み取られる場合、それはダーティリードと呼ばれ、トランザクションの分離に違反します。ダーティ リードとは、トランザクションがデータにアクセスし、データを変更したが、その変更がまだデータベースに送信されていないときに、別のトランザクションもデータにアクセスし、そのデータを使用することを意味します。 2). 反復不可能な読み取り は、トランザクション内で同じデータを複数回読み取ることを指します。このトランザクションが終了する前に、別のトランザクションも同じデータにアクセスします。次に、最初のトランザクションの 2 回のデータ読み取りの間に、2 番目のトランザクションの変更により 2 番目のトランザクションがコミットされます。その場合、最初のトランザクションで 2 回読み取られたデータは異なる可能性があります。このように、トランザクション内で 2 回読み取られるデータは異なるため、Non-Repeatable Read と呼ばれます。たとえば、編集者は同じ文書を 2 回読みますが、その合間に作成者が文書を書き直します。編集者が文書をもう一度読むと、文書は変更されています。生の読み取りは再現できません。この問題は、作成者がすべての執筆を終えた後にのみ編集者が文書を読み取ることができるようにすることで回避できます 3) ファントム読み取り: は、最初のトランザクションが独立して実行されない場合に発生する現象を指します。トランザクションはテーブル内のデータを変更します。この変更にはテーブル内のすべてのデータ行が含まれます。同時に、2 番目のトランザクションもこのテーブルのデータを変更します。この変更により、テーブルに新しいデータの行が挿入されます。その後、最初のトランザクションを操作するユーザーは、あたかも幻覚が起こったかのように、テーブル内にまだ変更されていないデータ行が存在することに気づくでしょう。たとえば、編集者が作成者によって送信されたドキュメントを変更しますが、プロダクションがその変更をドキュメントのマスター コピーにマージすると、作成者が新しい未編集の内容をドキュメントに追加したことがわかります。この問題は、編集者と制作部門が元のドキュメントの作業を完了するまで、誰もドキュメントに新しい内容を追加できないようにすれば回避できます。 まず次のようにテーブルを作成します: 事務B READ-COMMITTED,USE test;
CREATE TABLE `t` (
`a` int(11) NOT NULL PRIMARY KEY
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.1: ダーティリードとリピータブルリードの問題を説明します
トランザクションC-2 REPEATABLE-READ | トランザクション D SERIALIZABLE | set autocommit =0; |
| ||
|
トランス | アクションを開始; | |||
トランザクションを開始; t(a)values(4)に挿入; |
| ||||
t; | 1から*を選択してください,2,3,4 (ダーティ リード: コミットされていないトランザクションでのデータの読み取り) | select * from t; | 1,2,3 (ダーティ リードの解決) | ||
1, 2,3 | select * from t;1,2,3 | select * from t;1,2,3 |
|
|
|
t: | 1,2から*を選択してください、 3,4 |
select * from t: 1,2,3,4 |
select * from t: 1,2,3,4 (上記と同じトランザクションではないため、次のように読み取られます)トランザクションコミット 最新のものなので読み込めます 4) |
select * from t: 1,2,3 (繰り返し読み込み:上記と同じトランザクション内なので、トランザクションのデータのみ開始トランザクションが読み取られ、読み取りを繰り返すだけです) |
select * from t: 1,2,3,4 |
commit (トランザクションをコミット、以下は新しいトランザクションなので、トランザクションの送信後に最新のデータを読み取ることができます) |
|||||
select * from t: 1,2,3,4 |
|||||
READ- UNCOMMITTED はダーティ リードを生成し、実際のシナリオに適用されることはほとんどないため、基本的には使用されません。 |
トランザクション A |
トランザクション B READ-COMMITTED |
トランザクション C REPEATABLE-READ |
|||||||||||||||||||||||||||||||||||||||||||||||||||
セットautocommit =0; |
|||||||||||||||||||||||||||||||||||||||||||||||||||||
トランザクションを開始; |
トランザクションを開始; |
トランザクションを開始; |
|||||||||||||||||||||||||||||||||||||||||||||||||||
t(a)値に挿入(4); |
|||||||||||||||||||||||||||||||||||||||||||||||||||||
tから*を選択してください。 コミット; |
|||||||||||||||||||||||||||||||||||||||||||||||||||||
選択* from t: | 1,2,3,4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
1 , 2, 3 (繰り返し読み出し:上記と同じトランザクション内なので、トランザクションのデータのみが開始)トランザクションが読み取られます、つまり、繰り返し読み取られます) | |||||||||||||||||||||||||||||||||||||||||||||||||||||
commit (トランザクションをコミットします。以下は新しいトランザクションなので、トランザクションが送信された後に最新のデータを読み取ることができます) | |||||||||||||||||||||||||||||||||||||||||||||||||||||
select * from t: 1,2,3,4 |
REPEATABLE-READ can トランザクションで読み取られたデータが反復可能であること、つまり、同じ読み取りであることを確認します (最初に読み取られると、他のトランザクションが新しいデータを送信した場合でも、同じトランザクションで再度読み取られることはありません。 | READ-COMMITTED は、最新のトランザクションによってコミットされたデータが確実に読み取られることを保証するだけです。 ||||||||||||||||||||||||||||||||||||||||||||||||||||
当然数据的可见性都是对不同事务来说的,同一个事务,都是可以读到此事务中最新数据的。如下,
2.3、实验三:测试SERIALIZABLE事务对其他的影响
2.4. 実験 4: ファントム リード一部の記事では、InnoDB の反復読み取りが「ファントム リード」(ファントム リード) を回避すると書いていますが、これは正確ではありません。実験を実行します: (以下の実験はすべて、ストレージ エンジンと分離レベルに注意する必要があります)
实验4-1:
このように、ファントム読み取りが発生し、テーブルにデータがないと思われますが、実際にはデータがすでに存在しており、送信後にデータの競合が発見されます。 実験 4-2: |
以上がMySQL InnoDB の 4 つのトランザクション レベルとダーティ リード、ノンリピート リード、ファントム リードとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。