mysqlの4つのトランザクション独立性レベル

4469 ワード

トランザクションとは
トランザクションはアプリケーション内の一連の厳密な操作であり、すべての操作が正常に完了する必要があります.そうしないと、各操作で行われた変更はすべて取り消されます.つまり、トランザクションには原子性があり、1つのトランザクションの一連の操作はすべて成功するか、1つもしないかのいずれかです.トランザクションの終了には2つあり、トランザクション内のしたがってステップがすべて正常に実行されると、トランザクションがコミットされます.いずれかのステップが失敗すると、ロールバック操作が発生し、トランザクションの開始までのすべての操作が取り消されます.
トランザクションのACID
1、原子性(Atomicity):トランザクションが開始された後、すべての操作が完了するか、すべてしないか、中間段階に停滞することはできません.トランザクションの実行中にエラーが発生すると、トランザクションが開始される前のステータスにロールバックされ、すべての操作が発生していないようになります.つまり事務は不可分な全体であり、化学で学んだ原子のように物質構成の基本単位である.
2、コンシステンシ(Consistency):トランザクションの開始前と終了後、データベースの整合性制約は破壊されません.例えばAはBに振り替えて、Aがお金を引いたはずがないのに、Bは受け取っていない.
3、独立性(Isolation):同じ時間に、1つのトランザクションが同じデータを要求することを許可し、異なるトランザクションを同時に実行する間に互いに干渉しない.例えば、Aが銀行カードからお金を引き出している場合、Aがお金を引き出す過程が終わるまで、Bはこのカードに振り替えることができません.
4、持続性(Durability):トランザクションが完了すると、トランザクションによるデータベースのすべての更新がデータベースに保存されます.その他の操作や障害は、その実行結果に影響を与えるべきではなく、ロールバックできません.
トランザクションの同時問題
1、ダーティリード:トランザクションAはトランザクションBが更新したデータを読み出してから、Bロールバック操作を行うと、Aが読み取ったデータはダーティデータ2、繰り返してはいけない:トランザクションAは複数回同じデータを読み出して、トランザクションBはトランザクションAが複数回読み出している間に、データを更新して提出して、トランザクションAが複数回同じデータを読み出した場合、結果が一致しない.3、幻読:システム管理者Aはデータベースの中のすべての学生の成績を具体的な点数からABCDE等級に変更したが、システム管理者Bはこの時に具体的な点数の記録を挿入し、システム管理者Aの変更が終わった後、もう一つの記録が変更されていないことに気づいた.まるで幻覚が発生したかのように、これを幻読と呼ぶ.
小結:再読不可と幻読は混同されやすく、再読不可は修正に重点を置き、幻読は新規または削除に重点を置く.再読み取り不可の問題を解決するには、条件を満たす行をロックするだけで、幻読み取りを解決するにはロックテーブルが必要です.
トランザクション独立性レベル
1、Read Uncommitted(コミットされていないコンテンツの読み取り)この独立性レベルでは、すべてのトランザクションに他のコミットされていないトランザクションの実行結果が表示されます.この独立性レベルは、他のレベルよりもパフォーマンスが優れていないため、実際のアプリケーションではあまり使用されません.コミットされていないデータを読み取ることをダーティリード(Dirty Read)ともいう.2、Read Committed(コミットされたコンテンツの読み取り)ほとんどのデータベース・システムのデフォルトの独立性レベルです(ただし、MySQLのデフォルトではありません).独立性の簡単な定義を満たしています.1つのトランザクションでは、トランザクションにコミットされた変更しか表示されません.この独立性レベルは、同じトランザクションの他のインスタンスがインスタンス処理の間に新しいcommitを返す可能性があるため、同じselectが異なる結果を返す可能性があるため、いわゆる重複不可能読み取り(Nonrepeatable Read)もサポートします.3、Repeatable Read(再読み込み可能)MySQLのデフォルトのトランザクション独立性レベルです.同じトランザクションの複数のインスタンスがデータを同時に読み込むと、同じデータ行が表示されることを保証します.しかし、理論的には、幻読(Phantom Read)というもう一つの厄介な問題を引き起こす.簡単に言えば、幻読みとは、ユーザがある範囲のデータ行を読み取ると、別のトランザクションがその範囲内に新しい行を挿入し、ユーザがその範囲のデータ行を読み取ると、新しい「幻」行が発見されることを意味する.InnoDBとFalconストレージエンジンは、この問題をマルチバージョン同時制御(MVCC,Multiversion Concurrency Control)メカニズムによって解決した.4、Serializable(シリアル化可能)これは最も高い独立性レベルであり、トランザクションのソートを強制することで、互いに衝突しないようにし、幻読みの問題を解決します.簡単に言えば、各読み出しデータ行に共有ロックを追加します.このレベルでは、大量のタイムアウト現象とロック競合を引き起こす可能性があります.mysqlのデフォルトのトランザクション独立性レベルはrepeatable-readです.
個々の独立性レベルの場合
CREATE TABLE `account` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(11) DEFAULT '', 
  `balance` decimal(10,2) DEFAULT NULL ,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4; 

1、リード未提出(1)クライアントAを開き、現在のトランザクションモードをread uncommitted(リード未提出)に設定し、クエリーテーブルaccountの初期値:(2)クライアントAのトランザクションが提出される前に、別のクライアントBを開き、テーブルaccountを更新する:(3)この場合、クライアントBのトランザクションはまだ提出されていないが、しかし、クライアントAはBが更新したデータを照会することができる:(4)クライアントBのトランザクションが何らかの理由でロールバックされると、すべての操作が取り消され、クライアントAが照会したデータは実は汚いデータである:(5)クライアントAで更新文update account set balance=balance-50 where id=4を実行し、Lucyのbalanceは200にならず、250である.不思議なことに、データが一致していないのではないでしょうか.そう考えると無邪気すぎます.アプリケーションでは、300-50=250を使用します.他のセッションがロールバックしていることを知りません.この問題を解決するには、コミットされた独立性レベルを読むことができます.
2、リードコミット(1)クライアントAを開き、現在のトランザクションモードをread committed(リードコミット済み)に設定し、クエリーテーブルaccountのすべてのレコード:(2)クライアントAのトランザクションコミット前に別のクライアントBを開き、テーブルaccountを更新する:(3)このとき、クライアント側Bのトランザクションはまだコミットされておらず、クライアントAはBが更新したデータをクエリーできない.ダーティリードの問題を解決しました:(4)クライアントBのトランザクションコミット(5)クライアントAは、前のステップと同じクエリを実行し、結果が前のステップと一致しない、すなわち、再読み取り不可の問題が発生しました
3、繰り返し読み取り可能(1)あるクライアントAを開き、現在のトランザクションモードをrepeatable readとする.クエリーテーブルaccountのすべてのレコード(2)クライアントAのトランザクションがコミットされる前に別のクライアントBを開き、テーブルaccountを更新してコミットする(3)クライアントAクエリーテーブルaccountのすべてのレコードをステップ(1)クエリー結果と一致してコミットする.再読み取り不可の問題は発生しなかった(4)クライアントAでは、update balance=balance-50 where id=1が実行され、balanceは350-50=300にはならず、lucyのbalance値はステップ(2)の300で計算されるので250であり、データの整合性は破壊されなかった.重複読み取り可能な独立性レベルではMVCCメカニズムが使用されており、select操作ではバージョン番号は更新されず、スナップショット読み取り(履歴バージョン)である.Insert、update、deleteは、現在の読み取り(現在のバージョン)であるバージョン番号を更新します.(5)クライアントBを再オープンし、新しいデータを挿入して提出する(6)クライアントAクエリーテーブルaccountのすべてのレコードで、新規データが検出されなかったため、幻読みは発生しなかった
4、シリアル化(1)クライアントAを開き、現在のトランザクションモードをserializableに設定し、クエリーテーブルaccountの初期値:(2)クライアントBを開き、現在のトランザクションモードをserializableに設定し、レコードエラーを挿入し、テーブルがロックされて挿入に失敗し、mysqlのトランザクション分離レベルがserializableの場合、テーブルがロックされるため、幻読みは発生しない.この独立性レベルの同時性は極めて低く,開発ではあまり用いられない.
https://www.cnblogs.com/huano...https://www.fangzhipeng.com/j...