spring @transaction

Concept of things

Characteristics of things (ACID):
Insert picture description here

原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
一致性: 执行事务前后,数据保持一致;
隔离性: 并发访问数据库时,一个用户的事物不被其他事物所干扰,各并发事务之间数据库是独立的;
持久性:  一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

Spring transaction management interface

PlatformTransactionManager:

(Platform) Transaction Manager

Spring并不直接管理事务,而是提供了多种事务管理器 ,他们将事务管理的职责委托给Hibernate或者JTA等
持久化机制所提供的相关平台框架的事务来实现。 Spring事务管理器的接口是: 
org.springframework.transaction.PlatformTransactionManager ,
通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器

Three methods are defined in the PlatformTransactionManager interface:

Public interface PlatformTransactionManager()...{  
    // Return a currently active transaction or create a new one, according to the specified propagation behavior
    //(根据指定的传播行为,返回当前活动的事务或创建一个新事务。)
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; 
    // Commit the given transaction, with regard to its status(使用事务目前的状态提交事务)
    Void commit(TransactionStatus status) throws TransactionException;  
    // Perform a rollback of the given transaction(对执行的事务进行回滚)
    Void rollback(TransactionStatus status) throws TransactionException;  
    } 

TransactionDefinition:

Transaction definition information (transaction isolation level, propagation behavior, timeout, read-only, rollback rules)

事务管理器接口 PlatformTransactionManager 通过
 getTransaction(TransactionDefinition definition) 方法来得到一个事务,
这个方法里面的参数是 TransactionDefinition类 ,这个类就定义了一些基本的事务属性。
TransactionDefinition接口中定义了5个方法以及一些表示事务属性的常量比如隔离级别、传播行为等等的常量

Insert picture description here

public interface TransactionDefinition {
    // 返回事务的传播行为
    int getPropagationBehavior(); 
    // 返回事务的隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据
    int getIsolationLevel(); 
    // 返回事务必须在多少秒内完成
    //返回事务的名字
    String getName();
    int getTimeout();  
    // 返回是否优化为只读事务。
    boolean isReadOnly();
} 

(1) Things isolation level

Dirty read : When a transaction is accessing data and making changes to the data, and this modification has not yet been committed to the database, another transaction also accesses the data and then uses the data. Because this data is data that has not yet been submitted, the data read by another transaction is "dirty data", and the operation based on "dirty data" may be incorrect.
Lost to modify : When a transaction reads a piece of data and another transaction also accesses the data, then after modifying the data in the first transaction, the second transaction also modifies the data. In this way, the modification result in the first transaction is lost, so it is called lost modification.
For example: transaction 1 reads the data in a table A = 20, transaction 2 also reads A = 20, transaction 1 modifies A = A-1, transaction 2 also modifies A = A-1, the final result A = 19, transaction The modification of 1 was lost.
Unrepeatable read (Unrepeatableread) : refers to reading the same data multiple times within a transaction. When this transaction has not ended, another transaction also accesses the data. Then, between the two read data in the first transaction, the data read by the first transaction twice may be different due to the modification of the second transaction. This happens when the data read twice in one transaction is not the same, so it is called non-repeatable read.
Phantom read : Phantom read is similar to non-repeatable read. It happens when a transaction (T1) reads a few rows of data, and then another concurrent transaction (T2) inserts some data. In the subsequent query, the first transaction (T1) will find some more records that do not exist, as if an illusion has occurred, so it is called phantom reading.
The difference between non-repeatability and phantom reading: the point of
non-repeatable reading is modification, and the point of phantom reading is to add or delete.
Five constants representing the isolation level are defined in the TransactionDefinition interface :
TransactionDefinition.ISOLATION_DEFAULT : Use the default isolation level of the back-end database, Mysql uses the REPEATABLE_READ isolation level by default Oracle uses the READ_COMMITTED isolation level by default.
TransactionDefinition.ISOLATION_READ_UNCOMMITTED : The lowest isolation level that allows reading of uncommitted data changes, which may cause dirty Read, phantom read, or non-repeatable read
TransactionDefinition.ISOLATION_READ_COMMITTED : allows reading data that has been submitted by concurrent transactions, which can prevent dirty reads, but phantom reads or non-repeatable reads may still occur
TransactionDefinition.ISOLATION_REPEATABLE_REA D: multiple reads of the same field The results are consistent, unless the data is modified by the transaction itself, which can prevent dirty reads and non-repeatable reads, but magic reads may still occur.
TransactionDefinition.ISOLATION_SERIALIZABLE : The highest isolation level, completely obey the ACID isolation level. All transactions are executed one by one in turn, so that there is no possibility of interference between transactions, that is, this level can prevent dirty reads, non-repeatable reads, and magic reads. But this will seriously affect the performance of the program. Normally, this level is not used.
The TransactionDefinition definition includes the following constants that represent propagation behavior:

(2) Transaction propagation behavior (in order to solve the transaction problem of calling each other between business layer methods):

When a transaction method is called by another transaction method, you must specify how the transaction should be propagated. For example: the method may continue to run in an existing transaction, or it may start a new transaction and run it in its own transaction. The TransactionDefinition definition includes the following constants that represent propagation behavior:

Support the current transaction:

TransactionDefinition. PROPAGATION_REQUIRED : If there is currently a transaction, then join the transaction; if there is no transaction, then create a new transaction.
TransactionDefinition. PROPAGATION_SUPPORTS : If there is currently a transaction, then join the transaction; if there is currently no transaction, then continue to run in a non-transactional way.
TransactionDefinition. PROPAGATION_MANDATORY : If there is currently a transaction, then join the transaction; if there is currently no transaction, throw an exception. (Mandatory: mandatory)

The case that does not support the current transaction:

TransactionDefinition. PROPAGATION_REQUIRES_NEW : Create a new transaction, if there is currently a transaction, then suspend the current transaction.
TransactionDefinition. PROPAGATION_NOT_SUPPORTED : Run in non-transactional mode, if there is currently a transaction, then suspend the current transaction.
TransactionDefinition. PROPAGATION_NEVER : Run in non-transactional mode, if there is currently a transaction, an exception is thrown.

Other situations:

TransactionDefinition. PROPAGATION_NESTED : If there is currently a transaction, create a transaction to run as a nested transaction of the current transaction; if there is currently no transaction, the value is equivalent to TransactionDefinition.PROPAGATION_REQUIRED.

It should be noted here that the first six transaction propagation behaviors were introduced by Spring from EJB, and they share the same concept. And PROPAGATION_NESTED is unique to Spring. The transaction started with PROPAGATION_NESTED is embedded in an external transaction (if there is an external transaction). At this time, the embedded transaction is not an independent transaction. It depends on the existence of the external transaction. Only by submitting the external transaction can it cause internal For the submission of transactions, nested sub-transactions cannot be submitted separately. If you are familiar with the concept of SavePoint in JDBC, nested transactions are easy to understand. In fact, nested subtransactions are an application of savepoints. A transaction can include multiple savepoints, each nested Sub-transactions. In addition, the rollback of external transactions will also cause the rollback of nested sub-transactions.

(3) Transaction timeout attribute (the maximum time a transaction is allowed to execute)

The so-called transaction timeout refers to the maximum time allowed for a transaction to execute. If the time limit is exceeded but the transaction has not been completed, the transaction is automatically rolled back. In TransactionDefinition, the timeout time is represented by the value of int, and the unit is second.

(4) Transaction read-only attribute (whether to perform read-only operations on transaction resources)

The read-only attribute of a transaction refers to read-only operations or read-write operations on transactional resources. The so-called transactional resources refer to those resources that are managed by transactions, such as data sources, JMS resources, and custom transactional resources. If it is determined to only perform read-only operations on transactional resources, then we can mark the transaction as read-only to improve the performance of transaction processing. In TransactionDefinition, boolean type is used to indicate whether the transaction is read-only.

(5) Rollback rules (define transaction rollback rules)

These rules define which exceptions will cause the transaction to roll back and which will not. By default, a transaction will only be rolled back when it encounters a runtime exception, but it will not be rolled back when it encounters a checked exception (this behavior is consistent with the EJB rollback behavior).
But you can declare that the transaction rolls back like a runtime exception when it encounters a specific checked exception. Similarly, you can also declare that the transaction does not roll back when it encounters certain exceptions, even if these exceptions are runtime exceptions.

TransactionStatus interface

The TransactionStatus interface is used to record the status of a transaction. This interface defines a set of methods for obtaining or judging the corresponding status information of a transaction. The
PlatformTransactionManager.getTransaction (...) method returns a TransactionStatus object. The returned TransactionStatus object may represent a new or existing transaction (if there is a qualified transaction in the current call stack).

public interface TransactionStatus{
    boolean isNewTransaction(); // 是否是新的事物
    boolean hasSavepoint(); // 是否有恢复点
    void setRollbackOnly();  // 设置为只回滚
    boolean isRollbackOnly(); // 是否为只回滚
    boolean isCompleted; // 是否已完成
} 

Insert picture description here
Multiple things
Most Spring applications require only one transaction manager, but in some cases, you may need to use multiple independent transaction managers in a single application. The value attribute of @Transactional annotation can be used to selectively specify the identity to be used PlatformTransactionManager

public class TransactionalService {

    @Transactional("order")
    public void setSomething(String name) { ... }

    @Transactional("account")
    public void doSomething() { ... }
}

Custom shortcut annotations
If you find that @Transactional reuses the same attributes in many different methods, Spring's meta annotation support allows you to define custom shortcut annotations for specific use cases

@Target({ElementType.METHOD,ElementType.TYPE})
@ Retention(RetentionPolicy.RUNTIME)
@Transactional(“order”)
 public  @interface OrderTx {
}

@Target({ElementType.METHOD,ElementType.TYPE})
@ Retention(RetentionPolicy.RUNTIME)
@Transactional(“account”)
 public  @interface AccountTx {
}

The previous example can be rewritten as:

public class TransactionalService {

    @OrderTx
    public void setSomething(String name) { ... }

    @AccountTx
    public void doSomething() { ... }
}

Things propagation
Insert picture description here
When propagation is set to PROPAGATION_REQUIRED, a logical transaction scope will be created for each method set by the application. Each such logical transaction scope can be individually determined to only roll back the state, and the external transaction scope is logically independent of the internal transaction scope. , All these ranges will map to the same physical transaction. Therefore, if the internal transaction (external caller does not know) silently marks the transaction as rollback only, the external caller will still call commit. The external caller needs to receive an UnexpectedRollbackException to clearly indicate that a rollback has been performed.
Insert picture description here
PROPAGATION_REQUIRES_NEW, in contrast to PROPAGATION_REQUIRED, uses completely independent transactions for each affected transaction range. In this case, the underlying physical transactions are different, so they can be independently committed or rolled back, and external transactions are not affected by the rollback status of internal transactions.

PROPAGATION_NESTED (nested) uses a single physical transaction with multiple savepoints, which can be rolled back to that transaction. This partial rollback allows the internal transaction scope to trigger the rollback of its scope, and the external transaction can continue the physical transaction, although some operations have been rolled back. This setting is usually mapped to a JDBC savepoint, so it only applies to JDBC resource transactions

Reference materials:
https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html
https://juejin.im/post/5b00c52ef265da0b95276091#heading-5
https: / /www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/index.html

Published 51 original articles · won praise 2 · Views 6374

Guess you like

Origin blog.csdn.net/wenwang3000/article/details/100590167