Spring事務伝達と隔離

7470 ワード

Spring事務伝達と隔離
本論文ではSpring注釈@Transationとその分離(isolation)と伝播(propagation)属性の設定を議論する.
1.@Transactionalコメント
@Transactional注はデータベース事務操作の方法で使用できます.そして、事務の関連属性を設定できます.隔離属性、タイムアウト属性、リードオンリー属性、ロールバック条件は、事務マネージャを指定することもできます.
1.1.実現の詳細
Springは、トランザクションの作成、提出、ロールバックを管理するために、プロキシまたはクラスのバイトコードを作成する.プロキシ方式Springを使用すると、内部メソッドを無視してトランザクションを呼び出すことができます.@Transaction注釈があっても無視されます.プロキシは他のクラスで呼び出される必要があります.例えば、1つの方法は、@Transactional注釈をcalMethodと表記し、Springはいくつかのトランザクション管理コードを包装して、方法の実行過程をめぐっている:
createTransactionIfNecessary();
try {
    callMethod();
    commitTransactionAfterReturning();
} catch (exception) {
    completeTransactionAfterThrowing();
    throw exception;
}
1.2@Transactionalで注釈を使う
事務注釈は、インターフェース、クラス、または直接的に方法においてもよい.実際には優先度によってカバーされますが、低いから高い優先度までは、インターフェース、親タイプ、クラス、インターフェース方法、親タイプの方法、種類の方法です.
クラスの注釈については、Springアプリケーションは注釈が付いていないpublicメソッドに設定され、prvate、protecte方法に注釈を使用すると、Springは無視されます.以下に例を通して説明する.
@Transactional
public interface TransferService {
    void transfer(String user1, String user2, double val);
}
通常はインターフェースに事務を設定することを勧めませんが、Spring Data@Repositoryの場合は可能です.ここではクラスに注釈カバーインターフェースまたは親の設定を追加します.
@Service
@Transactional
public class TransferServiceImpl implements TransferService {
    @Override
    public void transfer(String user1, String user2, double val) {
        // ...
    }
}
方法に注釈を追加すると、上書きの定義:
@Transactional
public void transfer(String user1, String user2, double val) {
    // ...
}
2.事務伝播
伝播性は業務ロジックの事務境界を定義する.Springは、伝播性設定に従って、起動または一時停止を担当しています.
Springは、伝播属性に応じてTransaction Managerを呼び出します.すべてのタイプのTransactionagerの部分的な伝播属性をサポートしています.いくつかの伝播属性はTransactionagerによって特定されています.以下、異なる伝搬属性について詳細に説明する.
2.1.REQUIRED
REQUIREDはデフォルト属性です.Springは活動事務があるかどうかを確認し、ない場合は新しい事務を作成します.そうでないと、業務ロジックは現在の活動事務に追加されます.
@Transactional(propagation = Propagation.REQUIRED)
public void requiredExample(String user) { 
    // ... 
}
デフォルト属性は指定しなくてもいいです.
@Transactional
public void requiredExample(String user) { 
    // ... 
}
対応疑似コードは以下の通りです.
if (isExistingTransaction()) {
    if (isValidateExistingTransaction()) {
        validateExisitingAndThrowExceptionIfNotValid();
    }
    return existing;
}
return createNewTransaction();
2.2.SUPPORTS
SUPPORTS属性では、Springはまずイベントがあるかどうかをチェックし、存在する場合は使用し、逆の場合は実行しない.
@Transactional(propagation = Propagation.SUPPORTS)
public void supportsExample(String user) { 
    // ... 
}
疑似コードに対応:
if (isExistingTransaction()) {
    if (isValidateExistingTransaction()) {
        validateExisitingAndThrowExceptionIfNotValid();
    }
    return existing;
}
return emptyTransaction;
2.3.MANDATORY
属性がMANDATORY属性に設定されている場合、イベントイベントイベントがある場合に使用します.逆に異常投げをすると、強制的に事務を使うことになります.
@Transactional(propagation = Propagation.MANDATORY)
public void mandatoryExample(String user) { 
    // ... 
}
疑似コードに対応:
if (isExistingTransaction()) {
    if (isValidateExistingTransaction()) {
        validateExisitingAndThrowExceptionIfNotValid();
    }
    return existing;
}
throw IllegalTransactionStateException;
2.4.NEVER
NEVER属性のロジック:活動事務があれば例外を投げます.
@Transactional(propagation = Propagation.NEVER)
public void neverExample(String user) { 
    // ... 
}
疑似コードに対応:
if (isExistingTransaction()) {
    throw IllegalTransactionStateException;
}
return emptyTransaction;
2.5.NOT_SUPPORTED
イベントトランザクションがあるならば、Springはまず現在のトランザクションを保留してから、業務ロジックは無事務で実行されます.
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void notSupportedExample(String user) { 
    // ... 
}
JTATransation Managerは開梱用の事務をサポートします.他の方法は、トランザクションに対する参照を保持し、スレッドコンテキストからそれをクリアすることによって、サスペンションをシミュレートする.
2.6.REQUIRES_NEW
REQUIRES_NEW属性は、イベントトランザクションがあればSpringに現在のトランザクションを保留し、新規のトランザクションを作成します.
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void requiresNewExample(String user) { 
    // ... 
}
NOT_とSUPPORTEDのように、JTATransation Managerが実際の事務を実行するために必要です.疑似コードは以下の通りです
if (isExistingTransaction()) {
    suspend(existing);
    try {
        return createNewTransaction();
    } catch (exception) {
        resumeAfterBeginException();
        throw exception;
    }
}
return createNewTransaction();
2.7.NESTED
NESTED属性に対してSpringは、トランザクションが存在するかどうかをチェックし、存在する場合は保存点をマークします.後続業務の執行に異常があったら、保存先にスクロールすることを意味します.イベントトランザクションがない場合は、REQUID属性と同じです.
DataSourceTransation Managerはこの属性をサポートしています.JTATransation Managerの実装もサポートされています.JpaTransaction ManagerはJDBC接続のみにNESTED属性をサポートしていますが、nected Transation Allowed属性がtrueであり、JDBCドライバが保存ポイントをサポートすると、JPA事務におけるJDBCコードも動作します.属性の設定は以下の通りです.
@Transactional(propagation = Propagation.NESTED)
public void nestedExample(String user) { 
    // ... 
}
3.事務分離
隔離属性はACID(Atomicity、Consincy、IsolationおよびDurability)のうちの一つであり、分離記述は同時トランザクションアプリケーションの変更がどのように相互に見えるかを示す.各隔離レベルは、事務中のゼロ以上の同時副作用を防止する:
  • 汚読(Dirty read):同時トランザクションで未送信の情報を読み出す
  • は重複して読んではいけません.同時トランザクションが同じ行を更新して提出された場合、繰り返して読む行は異なる値
  • を得ます.
  • 幻読(Photom read):他のトランザクションがクエリー行を追加または削除して提出されると、一定範囲のレコードの戻り値が異なる
  • を繰り返す.
    私たちは@Transactional:isolationを通じて事務の隔離レベルを設定することができます.Springは5つの列挙値を提供しています.DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE.
    3.1.デフォルト隔離属性
    Springで新規事務を作成する場合、デフォルト分離レベルはRDBMSを使用するので、データベースを変更する際は注意するべきです.また、異なった隔離属性を用いて方法のセットを呼び出すシーンを考慮し、通常の流れからの分離は、新しいトランザクションの作成時にのみ適用される.そのため、方法を隔離状態で実行させたくないです.Transation Manager:setValidate Existing Transationをtrueに設定しなければなりません.疑似コードは以下の通りです
    if (isolationLevel != ISOLATION_DEFAULT) {
        if (currentTransactionIsolationLevel() != isolationLevel) {
            throw IllegalTransactionStateException
        }
    }
    
    他の隔離レベルを見てみます.
    3.2.READ_UNCOMMITTED
    READ_UNCOMMITTEDは最も低い隔離レベルであり、最大化は同時訪問を許可する.上記3つの合併性副作用の影響を受けています.この隔離されたトランザクションは、他の同時トランザクションを読み取ってデータを提出していません.また、重複して読み取ることも、幻読みすることもできません.したがって、行を再読み込みするか、範囲クエリーを再実行するかで、異なる結果が得られます.方法またはクラスに隔離レベルを設定できます.
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void log(String message) {
        // ...
    }
    
    PostgresはREAD_をサポートしていません.UNCOMMITTED隔離属性はREAD_を使用します.代わりにCOMMITEDがあります.OracleもREAD_をサポートしていません.UNCOMMITTED
    3.3.READ_COMMITTED
    第二級隔離READ_COMMITTEDは汚れを防止し、他の副作用を併発する可能性があります.併発事務の未提出変更は影響がありませんが、提出済みの変更は再度照会しても変わります.分離コードを設定:
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void log(String message){
        // ...
    }
    
    READ_COMMITTED Postgres、SQL ServerおよびOracleのデフォルトレベル.
    3.4.REPEATABLE_READ
    三つ目の隔離レベルはREPEATABLE_です.READは、汚読防止と重複不可を防止するため、併発事務による変更の影響を受けません.検索行を繰り返すと、異なる結果は得られませんが、レコードが追加されたり、一部の行が削除されたりすることがあります.
    このレベルは失われた更新を防ぐことができます.2つ以上の同時トランザクションを読んで、同じギルドを更新します.REPEATABLE_READは同時に行にアクセスすることが全く許可されていませんので、更新が無くなることはありません.
    コードの設定:
    @Transactional(isolation = Isolation.REPEATABLE_READ) 
    public void log(String message){
        // ...
    }
    
    REPEATABLE_READ Mysqlのデフォルトレベルは、OracleはREPEATABLEをサポートしていません.READ
    3.5.SERIALIZABLE
    SERIALIZABLEは最高の隔離レベルです.上記の全ての問題を防止することができますが、同時にアクセスする効率が最小になります.つまり、SERIALIZABLEグループを同時に実行するということは、順序実行結果と同じです.コードの設定:
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void log(String message){
        // ...
    }
    
    4.まとめ
    この論文では、事務の伝達と隔離の性質を検討し、異なる属性の意味と同時事務への影響を詳細に説明した.