ホームページ >データベース >mysql チュートリアル >MySql_MySQL のトランザクションの包括的な理解
私は最近、トランザクションを使用した注文ベースのプロジェクトに取り組んでいます。私たちのデータベースは MySql を使用し、ストレージ エンジンはトランザクションを適切にサポートする innoDB を使用します。今回は不倫に関する知識を見ていきましょう。
なぜ不倫が必要なのでしょうか?
トランザクションは、注文システムや銀行システムなどのさまざまなシナリオで広く使用されています。次のシナリオがあるとします。ユーザー A とユーザー B は銀行の預金者です。今、AさんはBさんに500元を送金したいと考えています。次に、次のことを行う必要があります:
1. A の口座残高 > 500 元を確認します。
2. アカウントAから500元を差し引きます。3. アカウント B に 500 元を追加します。
通常のプロセスの後、アカウント A から 500 が差し引かれ、アカウント B に 500 が追加されました。全員が満足しました。アカウント A からお金が引き落とされた後にシステムに障害が発生した場合はどうなりますか? A は無駄に 500 を失い、B は自分のものであるはずの 500 を受け取りませんでした。上記の場合、前提条件が隠されています。A がお金を差し引き、B がお金を追加すると、同時に成功するか、同時に失敗します。それがビジネスに求められることなのです。取引とは何ですか?
トランザクションを定義する代わりに、トランザクションの特徴について話しましょう。ご存知のとおり、トランザクションは 4 つの ACID 特性を満たす必要があります。
1. A(原子性) 原子性。トランザクションの実行は分割不可能な最小単位と見なされます。トランザクション内の操作は、正常に実行されるか、すべてが失敗して一部だけがロールバックされるかのいずれかでなければなりません。2. C(一貫性) 一貫性。トランザクションの実行は、データベースの整合性制約に違反してはなりません。上記の例の 2 番目の操作の実行後にシステムがクラッシュした場合、A と B の合計金額は変わらないことが保証されます。
3. I(隔離)隔離。一般に、トランザクションの動作は相互に影響を与えるべきではありません。ただし、実際の状況では、トランザクション間の相互作用の程度は分離レベルの影響を受けます。詳細は記事の後半で説明します。
4. D(耐久性)持続性。トランザクションがコミットされた後、コミットされたトランザクションをディスクに永続化する必要があります。たとえシステムがクラッシュしても、提出されたデータが失われることはありません。
トランザクションの 4 つの分離レベル
前の記事で述べたように、トランザクションの分離は分離レベルの影響を受けます。では、トランザクションの分離レベルとは何でしょうか?トランザクションの分離レベルは、トランザクション間の可視性を定義するトランザクションの「利己性」の程度と考えることができます。分離レベルは次のタイプに分類されます:
1.READ UNCOMMITTED (コミットされていない読み取り)。 RU 分離レベルでは、トランザクション A によってデータに加えられた変更は、コミットされていない場合でもトランザクション B に表示されます。この問題はダーティ読み取りと呼ばれます。これは、分離度が低い分離レベルであり、実際のアプリケーションでは多くの問題を引き起こす可能性があるため、一般的には使用されません。2.コミットされた読み取り。 RC の分離レベルでは、ダーティ リードの問題は発生しません。トランザクション A によってデータに加えられた変更は、送信後にトランザクション B に表示されます。たとえば、トランザクション B が開かれ、データ 1 が読み取られ、次にトランザクション A が開かれ、データが 2 に変更され、送信され、B が表示されます。再度データを読み取ると、最新のデータが読み取られます 2. RC の分離レベルでは、反復不可能な読み取りの問題が発生します。この分離レベルは、多くのデータベースのデフォルトの分離レベルです。
3.REPEATABLE READ(繰り返し読み取り)。 RR の分離レベルでは、反復不可能な読み取りの問題は発生しません。トランザクション A によってデータに加えられた変更が送信されると、その変更はトランザクション A より前に開始されたトランザクションには表示されなくなります。たとえば、トランザクション B が開かれると、データ 1 が読み取られます。その後、トランザクション A が開かれ、データが 2 に変更され、B は再度データを読み取りますが、まだ 1 しか読み取れません。 RR の分離レベルでは、ファントム読み取りの問題が発生します。ファントム読み取りの意味は、トランザクションが特定の範囲の値を読み取り、別のトランザクションがこの範囲に新しいレコードを挿入すると、前のトランザクションがこの範囲の値を再度読み取り、新しく挿入されたデータを読み取ることです。 Mysql のデフォルトの分離レベルは RR ですが、mysql の innoDB エンジンのギャップ ロックはファントム リードの問題を正常に解決します。
4.SERIALIZABLE (シリアル化可能)。 Serializable は最高の分離レベルです。この分離レベルでは、すべての処理が強制的にシリアルに実行され、読み取られたデータのすべての行がロックされるため、多数のロック取得の問題が発生し、パフォーマンスが最悪になります。
4 つの分離レベルを理解するために、例を示します。図 1 に示すように、トランザクション A とトランザクション B が次々にオープンされ、データ 1 が複数回更新されます。 4 人の悪役が異なるタイミングでトランザクションを開始します。データ 1 にはどのような値が表示されますか?
写真1
最初の悪役は 1 ~ 20 の間の値を読み取ることができます。非コミット読み取りの分離レベルでは、他のトランザクションによるデータ変更も現在のトランザクションから認識されるためです。 2 番目の悪役は、1、10、20 を読み取ることができます。彼は、他のトランザクションによって送信されたデータのみを読み取ることができます。 3 番目の悪役が読み取るデータは、自身のトランザクションが開始された時間によって異なります。トランザクション開始時に読み取られる値は、トランザクションがコミットされる前に読み取られる値となります。 4 番目の悪役は、A 終了と B 開始の間でオンになっている場合にのみデータを読み取ることができますが、トランザクション A とトランザクション B の実行中はデータを読み取ることができません。 4 番目の悪役はデータの読み取り時にロックする必要があるため、トランザクション A と B の実行中にデータの書き込みロックが占有され、4 番目の悪役はロックを待機することになります。
図 2 は、さまざまな分離レベルが直面する問題を示しています。
写真2
明らかに、分離レベルが高くなるほど、リソース消費 (ロック) が増加するため、同時実行パフォーマンスは低くなります。正確に言うと、シリアル化可能な分離レベルでは同時実行性はありません。
写真3
MySql のトランザクション
トランザクションの実装はデータベース ストレージ エンジンに基づいています。ストレージ エンジンが異なれば、トランザクションのサポート レベルも異なります。 mysql のトランザクションをサポートするストレージ エンジンには、innoDB と NDB が含まれます。 innoDB は、mysql のデフォルトのストレージ エンジンです。デフォルトの分離レベルは RR であり、RR の分離レベルよりもさらに一歩進んで、マルチバージョン同時実行制御 (MVCC、Multiversion Concurrency Control) を通じて非反復読み取り問題を解決します。 、ギャップ ロック (つまり同時実行制御) を加えることにより、ファントム読み取りの問題が解決されます。したがって、innoDB の RR 分離レベルは実際にはシリアル化レベルの効果を実現し、比較的良好な同時実行パフォーマンスを維持します。 トランザクションの分離はロックによって実現され、トランザクションの原子性、一貫性、耐久性はトランザクション ログによって実現されます。トランザクション ログに関して言えば、やり直しと元に戻すことです。
1.やり直しログinnoDB ストレージ エンジンでは、トランザクション ログは、REDO ログと innoDB ストレージ エンジンのログ バッファー (InnoDB Log Buffer) を通じて実装されます。トランザクションが開始されると、トランザクション内の操作がまずストレージ エンジンのログ バッファに書き込まれます。トランザクションがコミットされる前に、これらのバッファされたログを永続化するために事前にディスクにフラッシュする必要があります。これは DBA がよく行うことです。 "log first" "(先行書き込みログ)。トランザクションがコミットされた後、バッファ プールにマップされたデータ ファイルはディスクにゆっくりと更新されます。このとき、データベースがクラッシュまたはダウンした場合、リカバリのためにシステムを再起動すると、REDO ログに記録されているログに基づいてデータベースをクラッシュ前の状態に復元できます。未完了のトランザクションは、回復戦略に応じて、引き続き送信またはロールバックできます。
システムが起動すると、REDO ログ用に連続したストレージ領域が割り当てられます。
REDO ログはシーケンシャルな追加方式で記録され、シーケンシャル IO を通じてパフォーマンスが向上します。すべてのトランザクションは REDO ログの記憶領域を共有し、それらの REDO ログはステートメントの実行順に交互にまとめて記録されます。簡単な例を次に示します:
レコード 1:
レコード 2:
レコード 3:
レコード 4:
レコード 5:
2.元に戻すログ
undo ログは主にトランザクションのロールバックに役立ちます。トランザクション実行処理では、REDOログの記録に加えて、一定量のUNDOログも記録されます。 UNDO ログには、各操作前のデータのステータスが記録されます。トランザクションの実行中にロールバックが必要な場合は、UNDO ログに基づいてロールバック操作を実行できます。単一トランザクションのロールバックは、現在のトランザクションによって実行された操作のみをロールバックし、他のトランザクションによって実行された操作には影響しません。
以下はトランザクションの取り消し+やり直しの簡略化されたプロセスです
2つの値AとBがあり、値1と2があるとします
1. トランザクションを開始します;
2. ログを元に戻すには A=1 を記録します。
3. A = 3を更新します;
4. A=3 をやり直しログに記録します。
5. B=2 を記録してログを元に戻します。6. B = 4を更新します。
7. ログ B = 4 をやり直します。8. REDO ログをディスクに更新します
9.コミット
ステップ 1 ~ 8 のいずれかでシステムがダウンし、トランザクションがコミットされなかった場合、トランザクションはディスク上のデータに影響を与えません。 8 から 9 の間でダウンした場合は、この時点では REDO ログが保持されているため、回復後にロールバックすることを選択することも、トランザクションの送信を完了し続けることを選択することもできます。 9 以降にシステムがダウンし、メモリ マップ内の変更されたデータをディスクにフラッシュ バックする時間がなかった場合、システムが復元された後、REDO ログに従ってデータをディスクにフラッシュ バックできます。
つまり、REDO ログはトランザクションの耐久性と一貫性を実際に保証し、UNDO ログはトランザクションの原子性を保証します。
分散トランザクション
分散トランザクションを実装するには、innoDB が提供するネイティブ トランザクション サポートを使用する方法や、メッセージ キューを使用して分散トランザクションの究極の一貫性を実現する方法が多数あります。ここでは主に innoDB の分散トランザクションのサポートについて説明します。
図に示すように、mysql の分散トランザクション モデル。このモデルは、アプリケーション (AP)、リソース マネージャー (RM)、およびトランザクション マネージャー (TM) の 3 つの部分に分かれています。
アプリケーションはトランザクションの境界を定義し、どのトランザクションを実行する必要があるかを指定します。
リソース マネージャーは、トランザクションにアクセスするためのメソッドを提供します。
トランザクションマネージャーは、グローバルトランザクション内のさまざまなトランザクションを調整し、参加します。分散トランザクションは2フェーズコミット方式を採用しています。最初のフェーズでは、すべてのトランザクション ノードが準備を開始し、準備ができていることをトランザクション マネージャーに伝えます。第 2 段階のトランザクション マネージャーは、各ノードにコミットするかロールバックするかを指示します。ノードに障害が発生した場合、トランザクションの原子性を確保するためにすべてのグローバル ノードをロールバックする必要があります。
概要
いつトランザクションを使用する必要がありますか?ビジネスが ACID シナリオを満たす必要がある限り、トランザクションのサポートは必要だと思います。特に注文システムや銀行システムではトランザクションが不可欠です。この記事では主にトランザクションの特徴とmysql innoDBのトランザクションサポートについて紹介します。不倫に関しては、この記事に記載されている内容よりもはるかに多くの知識が含まれています。この記事は単なる紹介に過ぎません。