ホームページ  >  記事  >  Java  >  Spring トランザクション原則の詳細な紹介

Spring トランザクション原則の詳細な紹介

黄舟
黄舟オリジナル
2017-03-25 11:09:221483ブラウズ

1. トランザクションの基本原則

Spring トランザクションの本質は、実際にはデータベースによるトランザクションのサポートです。データベースのトランザクション サポートがなければ、Spring はトランザクション機能を提供できません。純粋な JDBC 操作データベースの場合、トランザクションを使用したい場合は、次の手順に従うことができます:

  1. 接続を取得します Connection con = DriverManager.getConnection()

  2. トランザクションを開きます con.setAutoCommit(true/false) ;

  3. CRUDを実行

  4. トランザクションをコミット/トランザクションをロールバック con.commit() / con.rollback();

  5. 接続を閉じる conn.close();

Springのトランザクション管理を使用した後ステップ 2 と 4 のコードを記述することはできなくなりましたが、Spirng

http自動的に完了させます 。 Spring の作業は CRUD の前後でどのように行われるのでしょうか? この問題を解決するには、Spring のトランザクション管理全体の実装原理を、例として説明します。 設定ファイル

アノテーション
    Driver
  1. をオンにし、関連するクラスとメソッドを @Transactional アノテーションでマークします

    この時点で、Spring は開始時に関連する Bean を解析して生成します。関連するアノテーションを持つメソッドとこれらのクラスとメソッドはプロキシを生成し、@Transaction の関連パラメータに従って関連する設定を挿入します。これにより、関連するトランザクションがプロキシで処理されます (トランザクションの通常の送信が有効になり、トランザクションがロールされます)。例外が発生したときに戻る)

  2. True。データベース層のトランザクションの送信とロールバックは、binlog または redo ログを通じて実装されます

  3. 2. Spring トランザクションの伝播

    属性

Spring のいわゆる伝播属性。トランザクションは、複数のトランザクションが同時に存在する場合に定義されます。これらの属性は、TransactionDefinition で定義されます。

定数名

定数の説明

PROPAGATION_REQUIREDは、現在のトランザクションがない場合、新しいトランザクションを作成します。これがSpringのデフォルトのトランザクション伝播です。新しいトランザクション。現在トランザクションが存在する場合、新しいトランザクションは中断されます。これらは 2 つの独立したトランザクションであり、外側のトランザクションが失敗してロールバックされた後は、内側のトランザクションの実行結果は反映されません。内部トランザクションは失敗し、外部トランザクションによってキャプチャされる例外 PROPAGATION_SUPPORTSPROPAGATION_MANDATORY トランザクションが現在存在する場合は、現在のトランザクションを一時停止します。 非トランザクション的な方法で実行し、トランザクションが現在存在する場合は例外をスローします。 アクティブなトランザクションが存在する場合は、ネストされたトランザクションで実行されます。アクティブなトランザクションがない場合は、REQUIRED 属性が実行されます。ロールバック可能な複数のセーブポイントを持つ単一のトランザクションを使用します。内部トランザクションのロールバックは、外部トランザクションには影響しません。これは DataSourceTransactionManager トランザクション マネージャーでのみ機能します。

3. データベース分離レベル

をスローします。現在のトランザクションをサポートするためにロールバック操作
を処理することもできません。非トランザクション方式で実行されます。
は現在のトランザクションをサポートします。現在のトランザクションがない場合、例外がスローされます。 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

Spring の分離レベル

定数 説明
ISOLATION_DEFAULT これは、データベースのデフォルトのトランザクション分離レベルを使用する、PlatfromTransactionManager のデフォルトの分離レベルです。他の 4 つは JDBC 分離レベルに対応します。
ISOLATION_READ_UNCOMMITTED これはトランザクションの最も低い分離レベルであり、別のトランザクションがこのトランザクションのコミットされていないデータを参照できるようになります。この分離レベルでは、ダーティ読み取り、反復不能読み取り、ファントム読み取りが発生します。
ISOLATION_READ_COMMITTED は、あるトランザクションによって変更されたデータが、送信された後は別のトランザクションによってのみ読み取れるようにします。別のトランザクションは、このトランザクションのコミットされていないデータを読み取ることができません。
ISOLATION_REPEATABLE_READ このトランザクション分離レベルは、ダーティ リードと反復不可能な読み取りを防ぐことができます。ただし、ファントム読み取りが発生する可能性があります。
ISOLATION_SERIALIZABLE これは、最も高価ですが最も信頼性の高いトランザクション分離レベルです。トランザクションは順次実行として処理されます。

5. トランザクションのネスト

上記の理論的知識を通じて、データベース トランザクションと 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 の TransactionCallback インターフェースを使用してトランザクションを実装することをお勧めします。アノテーションを使用する必要がある場合は、盲目的に Spring トランザクション アノテーションを使用しないでください。スプリングトランザクション 伝達メカニズムと絶縁レベルを詳細に理解しておかないと、予期せぬ影響が発生する可能性があります。

以上がSpring トランザクション原則の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。