Transactions in Spring
What is a transaction
Transaction: It is the smallest unit of work for database operations. It is a series of operations performed as a single logical unit of work. These operations are submitted as a system as a whole, either executed or not executed; a transaction is a set of indivisible operations (Working logic unit)
In layman's terms, a series of operations to achieve a certain purpose either succeed together (transaction commit) or fail together (transaction rollback)
The most common example is money transfer:
Xiao Ming transfers money to Ruhua:
开启事务-------
① 从小明的账户扣除1000元
② 给如花的账户增加1000元
事务提交-------
Any step from the above example, if there is a problem, will cause the transaction to roll back.
From hitting up to getting married is the submission of the affairs, and the woman asks the man to pursue her again. Once the affairs are rolled back~
Four characteristics of business
ACID is the basic feature of the transaction: the formula (one original permanent isolation)
- Atomicity: A transaction is an atomic operation consisting of a series of actions. The atomicity of the transaction ensures that the actions are either all completed or completely ineffective.
- Consistency: After the transaction is executed, the database status is consistent with other business rules, such as transfer business, regardless of whether the transaction is executed successfully or not, the sum of the balances of the two accounts involved in the transfer should be unchanged
- Isolation: Isolation means that in concurrent operations, different transactions should be isolated, so that each concurrent transaction will not interfere with each other.
- Durability: Once the transaction is submitted successfully, all data operations in the transaction must be persisted in the database. Even if the database crashes immediately after the transaction is submitted, when the database is restarted, it must be ensured that the data is restored through some mechanism.
Native JDBC transaction operations
try {
// 设置是否自动提交
connection.setAutoCommit(false)
// 数据库操作 insert,update,delete
connection.commit()
} catch(Exception ex) {
// 回滚
connection.rollback()
} finally {
connection.setAutoCommit(true)
}
Transaction isolation level
Database transaction isolation levels are 4, from low to high are: Read uncomomitted(读取未被提交的数据)
, Read committed(读取以被提交的数据)
, Repeatable read(可重复读)
, Serializable(完全隔离)
. Moreover, in the concurrent operations of transactions, dirty reads, non-repeatable reads, phantom reads, and transaction loss may occur
Four isolation levels
Read UnCommitted
Read uncommitted, as the name implies, is that a transaction can read the data of another uncommitted transaction, which will result in dirty reads
Read Committed
这种使用的概率比较高,因为很多时候我们就以最后一次读取的为准
Read commit, as the name implies, is that a transaction cannot read data until another transaction is committed, which will cause non-repeatable reads.
Repeatable Read
相当于加锁,MySQL的默认级别
Repeated reading means that when starting to read data (the transaction is opened), modification operations are no longer allowed, and phantom reads may occur.
Serializable
The highest transaction isolation level. Under the changed level, transactions are executed serially, which can avoid dirty reads, non-repeatable reads, and phantom reads. However, this transaction isolation level is inefficient and consumes database performance, so it is generally not used
to sum up
The default transaction isolation level of most databases is:, Read Committed
such as SqlServer, Oracle
The default isolation level of MySQL is Repeatable Read
possible problems
Dirty read
读取了未提交的新事务,然后被回滚了
Transaction A reads the data that has not yet been committed in transaction B. If transaction B rolls back, A reads using the wrong data
Non-repeatable
读取了提交的新事物,指更新操作
Non-repeatable reading means that for a certain data in the database, multiple queries within the scope of a transaction but back to different values, this is due to the query interval, modified and submitted by another transaction
One solution to solve non-repeatable reading is to adjust the isolation level.
Phantom reading
读取了提交的新事物,指增删操作
In the multiple-read configuration of transaction A, transaction B performs new operations on the data, resulting in inconsistent data read by transaction A multiple times
Another understanding of phantom reading can be:
幻读就是指新增了数据记录条数,第一次查询数据记录数为1000,再次查询的时候,变成了1001,这个就是幻读
The difference between non-repeatable reading and phantom reading
Many people tend to confuse non-repeatable reading and phantom reading. Indeed, the two are somewhat similar. But non-repeatable reading focuses on update and delete, while phantom reading focuses on insert
- Non-repeatable reading, only records that meet the conditions need to be locked
避免不可重复读需要锁行就行
- Phantom reading should lock the records that meet the conditions and their close
避免幻读则需要锁表
So the biggest difference between non-repeatable reading and phantom reading is how to solve the problems they generate through the lock mechanism
Transaction lost
The first type of transaction is lost
称为:回滚丢失
For the first type of transaction loss, for example, A and B are executing a data at the same time, and then B transaction has been submitted, and then A transaction is rolled back, so that the operation of B transaction is lost due to the rollback of A transaction.
The second type of transaction is lost
称为:覆盖丢失
For the second type of transaction loss, also known as coverage loss, it is that A and B execute one data together, and both get one data at the same time, then B transaction is submitted first, but A transaction is submitted again, thus covering B transaction
How Spring configures transactions
具体说出一些关键的xml元素
Prepare the data sheet:
Entity class:
public class User {
private Integer id;
private String name;
private Integer money;
}
Dao:
Service: an error scenario by default
Programmatic transaction
XML configuration transaction: add configuration of transaction manager and transaction manager template in applicationContext.xml
Annotation mode configuration transaction manager and transaction manager template
Declarative transaction
基于AspectJ XML方式
Note: Based on TransactionProxyFactoryBean, the proxy method is an older method, we will not describe it here
Delete the configuration of the transaction management template in applicationContext.xml, which is the following configuration:
<!-- 事务管理的模板 -->
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager" />
</bean>
Add transaction definition and AOP configuration
<!--基于AspectJ 申明式事务XML配置方式-->
<!-- 定义一个增强 -->
<tx:advice id="txAdvice"
transaction-manager="transactionManager">
<!-- 增强(事务)的属性的配置 -->
<tx:attributes>
<!-- isolation:DEFAULT ,事务的隔离级别。
propagation:事务的传播行为.
read-only:false,不是只读
timeout:-1
no-rollback-for:发生哪些异常不回滚
rollback-for:发生哪些异常回滚事务
-->
<tx:method name="transfer" isolation="DEFAULT" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- aop配置定义切面和切点的信息 -->
<aop:config>
<!-- 定义切点:哪些类的哪些方法应用增强 -->
<aop:pointcut
expression="execution(* com.dk.beans.service..*.*(..))"
id="mypointcut" />
<!-- 定义切面: -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="mypointcut" />
</aop:config>
Change the business class to the original way
/**
* 沒有事務的转账的业务
* @param fromName
* @param toName
* @param money
*/
public void transfer(String fromName, String toName, Integer money) {
userDAO.out(fromName, money);// 转出钱
int x = 10;
if(x == 10)
throw new RuntimeException("出错啦!");
userDAO.in(toName, money);// 收入钱
}
Annotation-based declarative transaction:
Configure @EnableTransactionManagement on the configuration class to enable transactions. Delete @Bane related to the transaction in the annotation class
Complete transaction configuration via @Transactional above the UserService class or above the method:
@Service
@Transactional
public class UserService {
}
Declarative transactions can be configured according to the method corresponding to the beginning of the transaction
<!-- 以insert开头的方法配置事务 -->
<tx:method name="insert*" isolation="DEFAULT" propagation="REQUIRED"/>
Spring transaction propagation characteristics
Refers to how the transaction method should proceed when a transaction method is called by another transaction method. for example
public class PersonService {
@Transactional
public void laoda(){
System.out.println("老大的方法");
xiaodi();
}
@Transactional
public void xiaodi(){
System.out.println("小弟方法");
}
}
That is, when the method of the boss calls the method of the younger brother, what should be done with the younger brother's affairs?
Assuming that the method of the boss is abnormal, does the younger brother need to roll back?
Assuming that the younger brother’s method is abnormal, does the boss’s method need to be rolled back?
Do nothing
- PROPAGATION_NEVER: If there is no transaction execution, if there is an exception, it will be thrown
- PROPAGATION_NOT_SUPPORTED: If there is no non-transactional execution, if there is a direct suspension, then non-transactional execution
- This is prone to deadlock
Dispensable
- PROPAGATION_SUPPORTS: Use it if you have it, forget it if you don’t
Must have affairs
- PROPAGATION_REQUIRES_NEW: Whether to create a new transaction, if there is one, it will be suspended. That is to say, the transactions are completely isolated, one transaction does not affect other transactions
- PROPAGATION_NESTED: If not, create a new transaction; if there is, nest other transactions in the current transaction. Nested transaction means that the outer transaction is abnormal, and the inner transaction is all rolled back
- PROPAGATION_REQUIRED: (default configuration) If not, create a new transaction; if there is, join the current transaction
- PROPAGATION_MANDATORY: If not, throw an exception; if there is, use the current transaction.