私は最近、トランザクションを使用した注文ベースのプロジェクトに取り組んでいます。私たちのデータベースは MySql で、ストレージ エンジンはトランザクションを適切にサポートする innoDB です。今回は不倫に関する知識を見ていきましょう。
なぜ不倫が必要なのでしょうか?
トランザクションは、注文システムや銀行システムなどのさまざまなシナリオで広く使用されています。次のシナリオがあるとします。ユーザー A とユーザー B は銀行の預金者です。今、AさんはBさんに500元を送金したいと考えています。次に、次のことを行う必要があります:
1. A の口座残高を確認します
2. 口座 A から 500 元を差し引きます
3. 通常のプロセスが完了します。 . 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.繰り返し読める。 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番目の悪役は、AendとBstartの間にオンになっている場合にのみデータを読み取ることができますが、トランザクションAとトランザクションBの実行中はデータを読み取ることができません。 4 番目の悪役はデータの読み取り時にロックする必要があるため、トランザクション A と B の実行中にデータの書き込みロックが占有され、4 番目の悪役はロックを待機することになります。
図 2 は、さまざまな分離レベルが直面する問題を示しています。
図 2
明らかに、分離レベルが高くなるほど、リソース消費 (ロック) が大きくなり、同時実行パフォーマンスが低下します。正確に言うと、シリアル化可能な分離レベルでは同時実行性はありません。
図 3
MySql のトランザクション
トランザクションの実装はデータベース ストレージ エンジンに基づいています。ストレージ エンジンが異なれば、トランザクションのサポート レベルも異なります。 mysql のトランザクションをサポートするストレージ エンジンには、innoDB と NDB が含まれます。 innoDB は、mysql のデフォルトのストレージ エンジンです。デフォルトの分離レベルは RR であり、RR の分離レベルよりもさらに一歩進んで、マルチバージョン同時実行制御 (MVCC、Multiversion Concurrency Control) を通じて非反復読み取り問題を解決します。 、ギャップ ロック (つまり同時実行制御) を加えることにより、ファントム読み取りの問題が解決されます。したがって、innoDB の RR 分離レベルは実際にはシリアル化レベルの効果を実現し、比較的良好な同時実行パフォーマンスを維持します。 トランザクションの分離はロックによって実現され、トランザクションの原子性、一貫性、耐久性はトランザクション ログによって実現されます。トランザクション ログに関して言えば、やり直しと元に戻すことです。
1.redo ログ
innoDB ストレージ エンジンでは、トランザクション ログは innoDB ストレージ エンジンの redo ログとログ バッファー (InnoDB Log Buffer) を通じて実装されます。トランザクションが開始されると、トランザクション内の操作がまずストレージ エンジンのログ バッファに書き込まれます。トランザクションがコミットされる前に、これらのバッファされたログを永続化するために事前にディスクにフラッシュする必要があります。これは DBA がよく行うことです。 "log first" "(先行書き込みログ)。トランザクションがコミットされた後、バッファ プールにマップされたデータ ファイルはディスクにゆっくりと更新されます。このとき、データベースがクラッシュまたはダウンした場合、リカバリのためにシステムを再起動すると、REDO ログに記録されているログに基づいてデータベースをクラッシュ前の状態に復元できます。未完了のトランザクションは、回復戦略に応じて、引き続き送信またはロールバックできます。
システムの起動時に、REDO ログ用に連続ストレージ領域が割り当てられ、REDO ログはシーケンシャル追加方式で記録され、シーケンシャル IO によってパフォーマンスが向上します。すべてのトランザクションは REDO ログの記憶領域を共有し、ステートメントの実行順序に従って交互に REDO ログがまとめて記録されます。簡単な例を次に示します。
レコード 1:
レコード 2:
レコード 3:
レコード 4:
レコード 5:
2.undo ログ
undo ログは主にトランザクションのロールバックに使用されます。トランザクション実行処理では、REDOログの記録に加えて、一定量のUNDOログも記録されます。 UNDO ログには、各操作前のデータのステータスが記録されます。トランザクションの実行中にロールバックが必要な場合は、UNDO ログに基づいてロールバック操作を実行できます。単一トランザクションのロールバックは、現在のトランザクションによって実行された操作のみをロールバックし、他のトランザクションによって実行された操作には影響しません。
以下は、元に戻す+やり直しトランザクションの簡略化されたプロセスです
それぞれ値1と2を持つ2つの値AとBがあると仮定します
1 レコードA=1。ログを元に戻すには、
3. ログ A = 3 を更新します。
5. ログを元に戻すには、レコード B=2 を実行します。レコード B = 4 を再実行ログに記録します
8. 再実行ログをディスクに更新します
ステップ 1 ~ 8 のいずれかでシステムがダウンし、トランザクションがコミットされない場合、トランザクションは何も影響しません。ディスク上のデータ。 8 から 9 の間でダウンした場合は、この時点では REDO ログが保持されているため、回復後にロールバックすることを選択することも、トランザクションの送信を完了し続けることを選択することもできます。 9 以降にシステムがクラッシュし、メモリ マップ内の変更されたデータがディスクにフラッシュ バックされなかった場合、システムが復元された後、REDO ログに従ってデータをディスクにフラッシュ バックできます。
つまり、REDO ログはトランザクションの耐久性と一貫性を実際に保証し、UNDO ログはトランザクションの原子性を保証します。
分散トランザクション
分散トランザクションを実装するには、innoDB が提供するネイティブ トランザクション サポートを使用するか、メッセージ キューを使用して分散トランザクションの究極の一貫性を実現する方法が多数あります。ここでは主に innoDB の分散トランザクションのサポートについて説明します。
写真に示すように、mysqlの分散トランザクションモデル。このモデルは、アプリケーション プログラム (AP)、リソース マネージャー (RM)、およびトランザクション マネージャー (TM) の 3 つの部分に分かれています。
アプリケーションはトランザクションの境界を定義し、どのトランザクションを実行する必要があるかを指定します。
リソースマネージャーはトランザクションにアクセスする方法を提供します。通常はデータベースがリソースマネージャーです。
トランザクションマネージャーは、トランザクションに関与するすべての関係者を調整します。世界的な取引業務。
分散トランザクションは2フェーズコミット方式を採用しています。最初のフェーズでは、すべてのトランザクション ノードが準備を開始し、準備ができていることをトランザクション マネージャーに伝えます。第 2 段階のトランザクション マネージャーは、各ノードにコミットするかロールバックするかを指示します。ノードに障害が発生した場合、トランザクションのアトミック性を確保するために、すべてのグローバル ノードをロールバックする必要があります。
概要
トランザクションを使用する必要があるのはどのような場合ですか?ビジネスが ACID シナリオを満たす必要がある限り、トランザクションのサポートは必要だと思います。特に注文システムや銀行システムではトランザクションが不可欠です。この記事では主にトランザクションの特徴とmysql innoDBのトランザクションサポートについて紹介します。この記事に記載されている内容よりもはるかに多くの知識が関係しています。読者の皆様には、不十分な点があることをご容赦ください。
以上がMySql のトランザクションの詳細な図による説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。