?
トランザクションとは、データベース管理システムの実行における論理的な単位で、有限のデータベース操作のシーケンスで構成されます。データベーストランザクションには通常、データベースに対する一連の読み取り/書き込み操作が含まれます。格納には次の2つの目的があります:
- データベース操作のシーケンスが障害から正常な状態に回復するための手段と、異常な状態でも一貫性を維持するための手段を提供します。
- 複数のアプリケーションが同時にデータベースにアクセスする場合、これらのアプリケーション間に分離方法を提供することで、互いの操作が干渉し合うのを防ぐことができます。
隔離と隔離レベル
トランザクションと言えばACID(Atomicity, Consistency, Isolation, Durability、つまり原子性、一貫性、分離、耐久性)を思い浮かべると思いますが、今日はそのIの1つである "分離 "についてお話します。データベース上で複数のトランザクションが同時に実行されると、ダーティ・リードや再現不可能なリード、ファントム・リードなどが発生する可能性があります。これらの問題を解決するために "分離レベル "という概念が導入されましたが、分離レベルを強くすればするほど性能は低下するので、性能と分離レベルのバランスを取る必要があります。
Read uncommitted(コミットされていない読み取り):トランザクションは、そのトランザクションが行った変更が他のトランザクションから見えるようになる前にコミットします。ダーティリードが生成されます。
コミットされた読み取り:トランザクションは、そのトランザクションが行った変更が他のトランザクションから見えるようになる前にコミットします。繰り返し不可能な読み取りが生成されます。
繰り返し可能な読み取り: トランザクションの実行中に見られるデータは常にトランザクションの開始時に見られるデータと同じです。もちろん、反復可能な分離レベルでは、コミットされていない変更は他のトランザクションからは利用できません。ファントムリードが発生する可能性があります。
シリアライゼーション:その名の通り、同じ行のレコードに対して、"write "は "write lock "を、"read "は "read lock".読み取りロックと書き込みロックが競合した場合、後からアクセスするトランザクションは、前のトランザクションの完了を待ってから実行を継続しなければなりません。
コミットを読む | それは | それは | それは |
コミットを読む | 不可 | それは | それは |
反復可能 | 不可 | 不可 | それは |
連載 | 不可 | 不可 | 不可 |
主に提出された読み取りと繰り返し読み取りを区別することは困難なので、小さな例を見てください。最初にテーブルを作成し、データ1
create database test;
use test;
create table test(id int primary key);
insert into test(id) values(1);
トランザクション・クエリを開始して 1 | トランザクションの開始 |
クエリが1 | |
1を2に変更 | |
クエリはV1 | |
サービスBの提出 | |
クエリがV2 | |
取引Aの提出 | |
クエリがV3 |
トランザクションAの異なる分離レベル、つまり図中のV1、V2、V3の戻り値がどのようになるかを見てみましょう。
この時点では、トランザクションBはまだコミットしていませんが、結果は既にAによって見られています。したがって、V2とV3も2です。
分離レベルが "read commit "の場合、V1 の値は 1、V2 の値は 2 です。したがって、V3 の値も 2 です。
もし分離レベルが "繰り返し読み取り "であれば、V1とV2は1、V3は2です。V2が1である理由は、実行中にトランザクションが見るデータは実行前と実行後で同じでなければならないという要件に従っているからです。
分離レベルが "Serialisation "の場合、トランザクションBは "change 1 to 2 "を実行した時点でロックされます。トランザクションBはトランザクションAがコミットするまで続行できません。従って、Aから見てV1とV2の値は1、V3の値は2です。
ビューはデータベース内部に作成され、アクセスはビューの論理的な結果に基づいて行われます。繰り返し読み取り" 分離レベルでは、このビューはトランザクションの開始時に作成され、トランザクションの間使用されます。read-commit" 分離レベルでは、ビューは各 SQL 文の実行開始時に作成されます。注意すべき点は、"read uncommitted" 分離レベルではレコードの最新の値を直接返すだけで、ビューという概念はないということです。
では、どのような場合に「読み直し可能な」シナリオが必要になるのでしょうか?
個人の銀行口座のテーブルを管理しているとします。1つのテーブルには毎月末の残高が、1つのテーブルには請求の詳細が格納されています。この時点で、データの照合を行わなければなりません。 つまり、前月の残高と現在の残高の差が、当月の請求明細と同じかどうかを判断しなければなりません。照合プロセス中にユーザが新しい取引を行ったとしても、照合の結果に影響しないようにします。
トランザクション分離の実装
MySQL では、事実上すべてのレコードが更新され、同時にロールバック操作が記録されます。レコードの最新の値は、ロールバック操作によって、すべて前の状態の値を取得します。値が 1 から 2、3、4 の順に変更されたと仮定すると、ロールバックログ内には以下のようなレコードが記録されます。
図のように、ビューA、B、Cでは、このレコードの値はそれぞれ1、2、4であり、システムには同じレコードの複数のバージョンが存在する可能性があります。つまり、データベースの複数バージョンの同時実行制御です。リードビューAの場合、1を取得するには、図のロールバック操作をすべて順番に実行して現在の値を取得する必要があります。現在4を5に変更している別のトランザクションがあったとしても、このトランザクションがリードビューA、B、Cの対応するトランザクションと衝突することはありません。
ロールバック・ログはいつまでも保存されるわけではありませんよね?
それが必要でなくなるのはいつですか?
なぜ ⻓ 取引を使わないといけないのですか?