Spring トランザクションの本質は、実際にはデータベースによるトランザクションのサポートです。データベースのトランザクション サポートがなければ、Spring はトランザクション機能を提供できません。純粋な JDBC 操作データベースの場合、トランザクションを使用したい場合は、次の手順に従うことができます:
http自動的に完了させます 。 Spring の作業は CRUD の前後でどのように行われるのでしょうか? この問題を解決するには、Spring のトランザクション管理全体の実装原理を、例として説明します。 設定ファイル
アノテーションこの時点で、Spring は開始時に関連する Bean を解析して生成します。関連するアノテーションを持つメソッドとこれらのクラスとメソッドはプロキシを生成し、@Transaction の関連パラメータに従って関連する設定を挿入します。これにより、関連するトランザクションがプロキシで処理されます (トランザクションの通常の送信が有効になり、トランザクションがロールされます)。例外が発生したときに戻る)
属性
をスローします。現在のトランザクションをサポートするためにロールバック操作 | ||
を処理することもできません。非トランザクション方式で実行されます。 | ||
は現在のトランザクションをサポートします。現在のトランザクションがない場合、例外がスローされます。 | PROPAGATION_NOT_SUPPORTED | |
PROPAGATION_NEVER | ||
PROPAGATION_NESTED | ||
分離レベル | 分離レベル値 | 発生した問題 |
Read-Uncommitted | 0 | ダーティリードにつながる |
Read-Committed | 1 | ダーティ リードを回避し、非反復読み取りとファントム読み取りを許可します |
Repeatable-Read | 2 | ダーティ リード、非反復読み取りを回避し、ファントム読み取りを許可します |
Serializable | 3 | Serializable Read 、トランザクション1 つずつのみ実行できるため、ダーティ リード、反復不可能な読み取り、ファントム リードが回避されます。実行効率が遅いため、注意して使用してください |
ダーティリード: 1 つのトランザクションがデータを追加、削除、または変更したが、コミットされていないデータを別のトランザクションが読み取ることができます。この時点で最初のトランザクションがロールバックされると、2 番目のトランザクションがダーティ データを読み取ることになります。
非反復読み取り: トランザクション内で 2 回の読み取り操作が発生し、最初の読み取り操作と 2 回目の操作の間に別のトランザクションがデータを変更します。このとき、2 回読み取られたデータは不整合になります。
ファントム読み取り: 最初のトランザクションは特定の範囲のデータに対する変更をバッチ処理し、2 番目のトランザクションはこの範囲にデータを追加します。このとき、最初のトランザクションは新しく追加されたデータの変更を失います。
概要:
分離レベルが高いほど、データの完全性と一貫性が保証されますが、同時実行パフォーマンスへの影響は大きくなります。
ほとんどのデータベースのデフォルトの分離レベルは、SqlServer、Oracle などの読み取りコミットです
いくつかのデータベースのデフォルトの分離レベルは次のとおりです: 反復可能な読み取り 例: MySQL InnoDB
定数 | 説明 |
ISOLATION_DEFAULT | これは、データベースのデフォルトのトランザクション分離レベルを使用する、PlatfromTransactionManager のデフォルトの分離レベルです。他の 4 つは JDBC 分離レベルに対応します。 |
ISOLATION_READ_UNCOMMITTED | これはトランザクションの最も低い分離レベルであり、別のトランザクションがこのトランザクションのコミットされていないデータを参照できるようになります。この分離レベルでは、ダーティ読み取り、反復不能読み取り、ファントム読み取りが発生します。 |
ISOLATION_READ_COMMITTED | は、あるトランザクションによって変更されたデータが、送信された後は別のトランザクションによってのみ読み取れるようにします。別のトランザクションは、このトランザクションのコミットされていないデータを読み取ることができません。 |
ISOLATION_REPEATABLE_READ | このトランザクション分離レベルは、ダーティ リードと反復不可能な読み取りを防ぐことができます。ただし、ファントム読み取りが発生する可能性があります。 |
ISOLATION_SERIALIZABLE | これは、最も高価ですが最も信頼性の高いトランザクション分離レベルです。トランザクションは順次実行として処理されます。 |
上記の理論的知識を通じて、データベース トランザクションと Spring トランザクションのいくつかの属性と特性を大まかに理解しました。次に、Spring トランザクションをより深く理解するために、いくつかのネストされたトランザクション シナリオを分析します。伝播のメカニズム。
外部トランザクションサービスAのメソッドA()が内部サービスBのメソッドB()を呼び出すとします
PROPAGATION_REQUIRED(春のデフォルト)
ServiceB.methodB()のトランザクションレベルがPROPAGATION_REQUIREDとして定義されている場合、ServiceA .methodA() が呼び出されたとき、Spring はすでにトランザクションを開始しています。この時点で ServiceB.methodB() は ServiceA.methodA() のトランザクション内ですでに実行されていると認識します。新しいトランザクションは開始されなくなります。
ServiceB.methodB() の実行中にトランザクション内にないことが判明した場合、それ自体にトランザクションが割り当てられます。
このように、ServiceA.methodA() または ServiceB.methodB() 内のどこかで例外が発生した場合、トランザクションはロールバックされます。
PROPAGATION_REQUIRES_NEW
たとえば、ServiceA.methodA() のトランザクション レベルが PROPAGATION_REQUIRED になるように設計し、ServiceB.methodB() のトランザクション レベルが PROPAGATION_REQUIRES_NEW になるように設計します。
その後、ServiceB.methodB()が実行されると、ServiceA.methodA()が配置されているトランザクションは一時停止され、ServiceB.methodB()は新しいトランザクションを開始し、ServiceB.methodB()トランザクションの完了を待ちます。 . それはただ続きます。
PROPAGATION_REQUIRED との違いは、トランザクションのロールバックの程度です。 ServiceB.methodB() は新しいトランザクションを開始するため、2 つの異なるトランザクションが存在します。 ServiceB.methodA() が送信されている場合、ServiceA.methodA() は失敗してロールバックしますが、ServiceB.methodB() はロールバックしません。 ServiceB.methodA() がロールバックに失敗した場合でも、ServiceB.methodA() がスローする例外が ServiceA.methodA() によってキャッチされた場合でも、ServiceA.methodA() トランザクションは引き続き送信される可能性があります (主に、B によってスローされた例外が例外であるかどうかによって異なります)。 A はロールバックされます)。
PROPAGATION_SUPPORTS
ServiceB.methodB() のトランザクションレベルが PROPAGATION_SUPPORTS であると仮定すると、ServiceB.methodB() を実行するときに、ServiceA.methodA() が既にトランザクションをオープンしていることが判明した場合、現在のトランザクションに参加します。 ServiceA.methodA() がトランザクションをオープンしていないことが判明した場合、トランザクション自体はオープンされません。このとき、内部メソッドのトランザクション性は最外部のトランザクションに完全に依存します。
PROPAGATION_NESTED
ここで、ServiceB.methodB() のトランザクション属性は PROPAGATION_NESTED として構成されます。ロールバックの場合、この 2 つは内部的にどのように連携するのでしょうか? #methodB) は、実行される前に SavePoint にロールバックされます。外部トランザクション (つまり、ServiceA#methodA) は、次の 2 つの方法で処理できます:
a. 例外をキャプチャし、例外分岐ロジックを実行します
void methodA() { try { ServiceB.methodB(); } catch (SomeException) { // 执行其他业务, 如 ServiceC.methodC(); } }
これは、ネストされたトランザクションの最も重要な部分でもあり、ServiceB.methodC() が実行される前に SavePoint にロールバックされるため、ServiceB.methodC() はブランチ実行に影響します。ダーティ データ (このメソッドが一度も実行されていないことに相当) の場合、この機能は一部の特殊なビジネスで使用できますが、PROPAGATION_REQUIRED も PROPAGATION_REQUIRES_NEW もこれを行うことはできません。
b. 外部トランザクションのロールバック/コミット コードは変更を加えず、内部トランザクション (ServiceB#methodB) がロールバックすると、最初に ServiceB.methodB が実行される前の SavePoint にロールバックされます (これは次の場合に当てはまります)。他の 3 つのトランザクション伝播属性は基本的に使用されないため、ここでは分析されません。
6. まとめ
以上がSpring トランザクション原則の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。