トランザクションのプロパティ
- 原子性:トランザクションは原子操作であり、一連のアクションで構成されます。トランザクションの原子性により、アクションが完全に完了するか、まったく動作しないかのいずれかが保証されます;
- 一貫性:トランザクションが完了したら、システムはモデル化しているビジネスが一貫した状態にあることを保証しなければなりません。現実にはデータが破損してはいけません;
- 分離:同じデータを扱うトランザクションが同時に多数存在する可能性があるため、データの破損を防ぐために各トランザクションは他のトランザクションから分離して開発する必要があります;
- 永続性:トランザクションが完了すると、その結果はどのようなシステムエラーが発生しても影響を受けないようにする必要があります。通常、トランザクションの結果は永続メモリに書き込まれます;
Springトランザクションの設定方法
Springは、プログラム的トランザクション管理と宣言的トランザクション管理の両方をサポートしています。
- 宣言的なトランザクション管理宣言的なトランザクション管理は、AOPの上に構築され、その本質は、メソッドの前後にインターセプトし、ターゲットメソッドの開始時にトランザクションを作成または参加し、状況の実行後にターゲットメソッドの実行に応じて提出またはロールバックすることです。プログラム上のトランザクションは、毎回別の実装を達成するために、しかし、複雑な機能のビジネスボリュームは、プログラム上のトランザクションの使用は間違いなく苦痛であり、宣言的トランザクションが異なっている、宣言的トランザクションは、非侵入的であり、ビジネスロジックの実装に影響を与えません、あなただけのトランザクションルールの宣言に関連する設定ファイルで行う必要がある、または方法のアノテーションを介して、ビジネスロジックにトランザクションルールを適用することができます。明らかに、宣言的なトランザクション管理は、Springが提唱する非侵入的なプログラミングアプローチであるプログラム的なトランザクション管理よりも優れています。唯一の欠点は、宣言型トランザクション管理の粒度がメソッドレベルであるのに対して、プログラム型トランザクション管理はコードブロックにすることができますが、宣言型トランザクション管理の設定を完了するためにメソッドを抽出することができます。
トランザクションの伝播の振る舞い
トランザクションの伝播は、一般的にトランザクションのネスティングシナリオでは、別のトランザクションメソッドへの呼び出しの中にトランザクションメソッドとして使用されるので、2つのメソッドは、独立したメソッドとして提出するか、または内側のトランザクションが一緒に提出する外側のトランザクションにマージされるかどうか、これはトランザクションの伝播メカニズムの構成を実行する方法を決定するための必要性です。
- PROPAGATION_REQUIRED****Springのデフォルトのプロパゲーションメカニズムで、ビジネスニーズの大部分を満たします。
- PROPAGATION_REQUIRES_NEW****このトランザクション伝搬の動作は、毎回新しいトランザクションをオープンし、同時に外側のトランザクションをハングし、現在のトランザクションが終了したときに上位のトランザクションの実行を再開します。外側のレイヤにトランザクションがない場合、新しくオープンされたトランザクショ ンが実行されます。
- PROPAGATION_SUPPORTS****は、外層がトランザクションを持っている場合は外層のトランザクションに参加し、外層がトランザクションを持っていない場合は、非トランザクションメソッドを使用して直接実行します。外層のトランザクションに完全に依存します。
- PROPAGATION_NOT_SUPPORTED****この伝播動作はトランザクションをサポートしていません。外側のレイヤーにトランザクションが存在する場合、それはハングし、現在のコードの実行後、外側のトランザクションが再開され、例外の有無にかかわらず、現在のコードはロールバックされません
- PROPAGATION_NEVER**** この伝播動作は外部トランザクションをサポートしません。
- PROPAGATION_MANDATORY**** Neverとは逆に、外部レベルにトランザクションがない場合は例外をスローします。
- PROPAGATION_NESTED****は、ネストされたトランザクションが既に存在する場合、その中でメソッドを実行することを示します。入れ子になったトランザクションは、現在のトランザクションとは独立して個別にコミットまたはロールバックすることができ、現在のトランザクションが存在しない場合の動作はPROPAGATION_REQUIREDと同じです。伝播の動作は、状態を保存する機能によって特徴付けられ、現在のトランザクションは、このようにすべてのネストされたトランザクションがロールバックされる、つまり、各ロールバックは、子トランザクションが例外を食べない場合は、基本的にはまだすべてのロールバックを引き起こす、独自のロールバックを回避するために、特定のポイントにロールバックされます。
トランザクション伝播の振る舞いは、新しいトランザクションを開始すべきかハングすべきか、あるいはメソッドをトランザクションコンテキストで実行すべきか、という疑問に答えるものです。
現在のトランザクションをサポートします:
TransactionDefinition.PROPAGATION_REQUIRED:トランザクションが現在存在する場合、そのトランザクションに参加します。TransactionDefinition.PROPAGATION_MANDATORY : トランザクションが現在存在する場合、トランザクションに参加します。現在のトランザクションはサポートされていません:
transactionDefinition.PROPAGATION_REQUIRES_NEW : 新しいトランザクションを作成するか、または現在のトランザクションが存在する場合はハングします。 transactionDefinition.PROPAGATION_NOT_SUPPORTED : 非トランザクション方式で実行するか、または現在のトランザクションが存在する場合はハングします。TransactionDefinition.PROPAGATION_NEVER : 非トランザクション方式で実行し、現在トランザクションが存在する場合は例外をスローします。TransactionDefinition.PROPAGATION_NEVER:
TransactionDefinition.PROPAGATION_NESTED: 現在トランザクションが存在する場合、現在のトランザクションのネストされたトランザクションとして実行するトランザクションを作成します。現在のトランザクションが存在しない場合、この値は TransactionDefinition.PROPAGATION_REQUIRED と同等です。.
トランザクションの分離レベル
トランザクションの分離レベル:あるトランザクションが他の同時実行トランザクションの活動の影響を受ける可能性の度合い。
典型的なアプリケーションでは、複数のトランザクションが同時に実行され、多くの場合、作業を完了するために同じデータを操作します。
- ダーティリードダーティリードは、あるトランザクションが、他のトランザクションによって上書きされ、 まだコミットされていないデータを読み取るときに発生します。これらの変更が後でロールバックされた場合、最初のトランザクションが読み込んだデータは無効となります。
- 繰り返し不可能な読み取り繰り返し不可能な読み取りは、トランザクションが同じ照会を2回以上実行し、結果が毎回異なる場合に発生します。
繰り返し読まない読書は復習に重点
- ファントム・リードファントム・リードは、繰り返し不可能なリードと似ています。ファントムリードは、あるトランザクションが数行を読み込んだ後、別の同時実行トランザクションが数行を挿入した場合に発生します。後のクエリで、最初のトランザクションはそこになかった行を追加で発見します。
ファントムリーディングは、追加や削除に重点を置いています。
- ロスト・モディフィケーションあるトランザクションがデータを読み取り、別のトランザクションもそのデータにアクセスした場合、最初のトランザクションでそのデータを修正した後、2番目のトランザクションもそのデータを修正します。そのため、最初のトランザクションで修正された結果は失われ、ロスト・モディフィケーションと呼ばれます。
理想的には、トランザクションは互いに完全に分離され、このような問題の発生を防ぐことができます。しかし、分離はしばしばデータベース内のレコードをロックすることを含むため、完全な分離はパフォーマンスに影響を与える可能性があります。完全な分離はトランザクション同士が作業を完了するまで待つ必要があり、同時実行を妨げる可能性があるため、ビジネス・シナリオに応じて異なる分離境界を選択することができます。
- ISOLATION_DEFAULT バックエンド・データベースのデフォルトの分離レベルを使用します;
- ISOLATION_READ_UNCOMMITTED****は、コミットされていない変更の読み取りを許可します;
- ISOLATION_READ_COMMITTED****オラクルのデフォルトの分離境界で、既にコミットされた同時実行トランザクションからの読み取りを許可します。ダーティ・リードが防止されますが、ファントム・リードや再現不可能なリードが発生する可能性があります。
- ISOLATION_REPEATABLE_READ MySQLのデフォルト分離レベルで、現在のトランザクション自体によってデータが変更されない限り、同じフィールドを複数回読み込んでも一貫した結果が得られます。ダーティで反復不可能な読み取りは防止されますが、ファントムリードが発生する可能性があります。
- ISOLATION_SERIALIZABLEは ACID分離レベルに完全に従い、ダーティリード、反復不可能リード、ファントム・リードが発生しないようにします。これは通常、現在のトランザクションに関係するデータ・テーブルを完全にロックすることで達成されるため、全ての分離レベルの中で最も遅いものでもあります。
読み込み専用
トランザクションがデータベース上で読み取り専用の操作を行う場合、データベースはそのトランザクションの読み取り専用という性質を利用して、特定の最適化を適用することがあります。トランザクションを読み取り専用と宣言することで、バックエンドデータベースは適切と思われる最適化を適用する機会を与えられます。読み取り専用の最適化は、トランザクションが開始されたときにバックエンドデータベースによって実装されるため、トランザクションを読み取り専用と宣言することは、新しいトランザクションを開始する可能性のある伝播動作を持つメソッドに対してのみ意味があります。
トランザクションのタイムアウト
アプリケーションのパフォーマンスを向上させるためには、トランザクションを長時間実行することはできません。
トランザクションが異常に長時間実行されるようになったとします。トランザクションはデータベースのロックを伴うことがあるため、長時間実行されるトランザクションは不必要にデータリソースを圧迫する可能性があります。そこで、トランザクションが終了するのを待つことなく、特定の秒数後に自動的にロールバックするように宣言することができます。
タイムアウトクロックはトランザクションが開始されたときに開始されるので、トランザクションタイムアウトを宣言することは、新しいトランザクションを開始する可能性のある伝播動作を持つメソッドに対してのみ意味があります。
ロールバックのルール
デフォルトの設定では、トランザクションは実行時例外が発生した場合にのみロールバックされ、チェック例外が発生した場合にはロールバックされません。
しかし、特定のチェックされた例外が発生したときに、あたかも実行時例外であるかの ように、トランザクションをロールバックすると宣言することは可能です。同様に、特定の例外が実行時例外であっても、特定の例外の発生時にトランザクショ ンをロールバックしないと宣言することも可能です。
コミットされていないデータの読み取りは基本的に不要
- トランザクションの伝播:@Transactional(propagation=Propagation.REQUIRED)
トランザクションのタイムアウト:@Transactional(timeout=30)
巻き返し
この属性は、ロールバックされる例外クラスの配列を設定するために使用されます。これにより、指定された例外配列の例外がメソッドでスローされると、トランザクションがロールバックされます。