background
Internet banking and electricity supplier industry, are most concerned about database transactions.
Core Business | Explanation |
---|---|
The financial industry - the amount of financial products | It does not allow an error |
Electricity supplier industry - the amount of commodity trading, commodity stocks | It does not allow an error |
Facing difficulties:
Highly concurrent guaranteed: data consistency, high performance;
spring treatment of things:
AOP uses technology provides transaction support, declarative transaction code to repeat try-catch-finally addition codes;
Scene two solutions:
Scenes | Solution |
---|---|
Inventory deductions, transaction records, account the amount of data consistency | Database transaction to ensure consistency |
Batch processing part of the task failure does not affect the rollback batch jobs | Database transaction propagation behavior |
jdbc-processing services
Code
package com.springbootpractice.demo.demo_jdbc_tx.biz;
import lombok.SneakyThrows;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Objects;
import java.util.Optional;
/**
* 说明:代码方式事务编程 VS 申明式事物编程
* @author carter
* 创建时间: 2020年01月08日 11:02 上午
**/
@Service
public class TxJdbcBiz {
private final JdbcTemplate jdbcTemplate;
public TxJdbcBiz(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@SneakyThrows
public int insertUserLogin(String username, String note) {
Connection connection = null;
int result = 0;
try {
connection = Objects.requireNonNull(jdbcTemplate.getDataSource()).getConnection();
connection.setAutoCommit(false);
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
final PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO user_login(user_name,password,sex,note) VALUES(?,?,?,?)");
preparedStatement.setString(1, username);
preparedStatement.setString(2, "abc123");
preparedStatement.setInt(3, 1);
preparedStatement.setString(4, note);
result = preparedStatement.executeUpdate();
connection.commit();
} catch (Exception e) {
Optional.ofNullable(connection)
.ifPresent(item -> {
try {
item.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
});
e.printStackTrace();
} finally {
Optional.ofNullable(connection)
.filter(this::closeConnection)
.ifPresent(item -> {
try {
item.close();
} catch (SQLException e) {
e.printStackTrace();
}
});
}
return result;
}
private boolean closeConnection(Connection item) {
try {
return !item.isClosed();
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
@Transactional
public int insertUserLoginTransaction(String username, String note) {
String sql = "INSERT INTO user_login(user_name,password,sex,note) VALUES(?,?,?,?)";
Object[] params = {username, "abc123", 1, note};
return jdbcTemplate.update(sql, params);
}
}
Test code
package com.springbootpractice.demo.demo_jdbc_tx;
import com.springbootpractice.demo.demo_jdbc_tx.biz.TxJdbcBiz;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.TransactionManager;
import org.springframework.util.Assert;
@SpringBootTest
class DemoJdbcTxApplicationTests {
@Autowired
private TxJdbcBiz txJdbcBiz;
@Autowired
private TransactionManager transactionManager;
@Test
void testInsertUserTest() {
final int result = txJdbcBiz.insertUserLogin("monika.smith", "xxxx");
Assert.isTrue(result > 0, "插入失败");
}
@Test
void insertUserLoginTransactionTest() {
final int result = txJdbcBiz.insertUserLoginTransaction("stefan.li", "hello transaction");
Assert.isTrue(result > 0, "插入失败");
}
@Test
void transactionManagerTest() {
System.out.println(transactionManager.getClass().getName());
}
}
Code has a very nasty place, is the try-catch-finally;
flow chart
AOP process with the overall process is very similar to the use of AOP, you can perform the steps of sql extracted achieve alone, other fixed processes in place to do the notification.
jdbc I use programming code point things!
Affirming transaction
To mark the transaction declarative annotation @Transaction, or can be standard methods in the class;
@Tranaction use position | Explanation |
---|---|
The class or interface | Class in all public non-static method will enable transaction, the Spring recommendation on implementation classes, aop must otherwise take effect when the agent interface based on the entry into force of |
Methodologically | This method |
@Transaction source code and configuration items
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.transaction.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
int timeout() default -1;
boolean readOnly() default false;
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}
Description:
Attributes | Explanation |
---|---|
isolation | Transaction isolation level |
propagation | Propagation behavior |
rollbackFor,rollbakcForClassName | Which will trigger abnormal transaction rollback |
value | Transaction Manager |
timeout | Transaction timeout |
readOnly | Whether it is read-only transaction |
noRollbackFor,noRollbackForClassName | What exception does not trigger a transaction rollback |
Affairs of the installation process:
springIOC container when activated, will @Transactional annotation parsed configuration information, and then save the transaction definer (TransactionDefinition), and record what kind of needs to initiate a transaction, what strategy to adopt to execute the transaction.
We have to do is mark @Transactional and configuration properties can be;
Process Figure:
Using greatly simplified manner;
Code
@Transactional
public int insertUserLoginTransaction(String username, String note) {
String sql = "INSERT INTO user_login(user_name,password,sex,note) VALUES(?,?,?,?)";
Object[] params = {username, "abc123", 1, note};
return jdbcTemplate.update(sql, params);
}
Transaction Manager
Open transaction, commit, rollback is placed on the transaction manager. TransactionManager;
TransactionManager Code
package org.springframework.transaction;
public interface TransactionManager {
}
This is an empty interface, the actual work is PlatfromTransactionManager;
PlatfromTransactionManager Code:
package org.springframework.transaction;
import org.springframework.lang.Nullable;
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
}
3 shelves transaction manager comparison:
Shelf | Transaction Management | Explanation |
---|---|---|
spring-jdbc | DatasourceTransactionManager | |
jpa | JpaTransactionManager | |
mybatis | DatasourceTransactionManager |
Code examples point mybatis me!
Transaction isolation level
Scene: electricity supplier industry inventory deductions, time is multithreaded environment deductions stock, for the database, there will be multiple transactions colleagues access to the same records, inconsistent data due this case, the loss is the database updated .
Database transaction 4 properties
That ACID
Characteristics of the transaction | English name | Explanation |
---|---|---|
Atomicity | Atomic | A transaction comprising a plurality of steps A, B, C, is the identification of these atomicity operations ISSUE all succeed or all fail, the third case will not |
consistency | Consistency | After the transaction is completed, all the data in a consistent state |
Isolation | Isolation | Process multiple threads to access the same data, each thread in a different transaction, in order to suppress generation of lost updates, given the isolation level, by providing the barrier properties, can suppress the occurrence of lost updates, where the presence of a selected |
Endurance | Durability | After the transaction, the data will persist, restart after a power failure also can be provided to continue to use the program |
Isolation level:
Isolation Levels | Explanation | problem | Concurrent performance |
---|---|---|---|
Uncommitted Read [read uncommitted] | Further data allows a transaction to read uncommitted transaction, the transaction is not applicable requirements is relatively high, the transaction suitable for less demanding scenario | Dirty read (single) | Concurrent highest performance |
Read Committed [read committed] | A transaction can only read another transaction has a data submitted | Non-repeatable read (single) | Concurrent performance in general |
Repeatable read] [read repeated | When the transaction will be submitted to determine whether the latest value changes | Fantasy reading (in terms of multiple data) | Concurrent poor performance |
Serialization [serializable] | All sql are executed in the order | Exactly the same data | Concurrent worst performance |
Selected based on
Isolation Levels | Dirty read | Non-repeatable read | Phantom read |
---|---|---|---|
Uncommitted Read | Yes | Yes | Yes |
Read Committed | no | Yes | Yes |
Repeatable read | no | no | Yes |
Serialization | no | no | no |
According to the actual scene allows to set the transaction isolation level;
Isolation level will bring the cost of the lock; optimization:
- Optimistic locking,
- redis distributed lock,
- zk distributed lock;
database | Transaction isolation level | The default transaction isolation level |
---|---|---|
mysql | Four kinds | Repeatable read |
oracle | Read Committed, serialized | Read Committed |
springboot configuration application default transaction isolation level: spring.datasource.xxx.default-transaction-isolation = 2
digital | The corresponding isolation level |
---|---|
-1 | no |
1 | Uncommitted Read |
2 | Read Committed |
4 | Repeatable read |
8 | Serialization |
Transaction propagation behavior
Communication behavior is a policy issue to call the transaction between the approach taken. Scene: a batch in a transaction A task, each individual has a separate transaction is a transaction Bn; subtasks rollback roll back the transaction does not affect the A's;
Source propagation behavior
package org.springframework.transaction.annotation;
import org.springframework.transaction.TransactionDefinition;
public enum Propagation {
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
NEVER(TransactionDefinition.PROPAGATION_NEVER),
NESTED(TransactionDefinition.PROPAGATION_NESTED);
private final int value;
Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
Include seven spread configuration properties, are described below:
Propagation behavior | Child behavior method in the presence of the parent method affairs | The behavior of sub-method transaction does not exist in the parent method |
---|---|---|
REQUIRED | The default propagation behavior, follow, | Create a new transaction |
SUPPORTS | Follow; | No transaction, no transaction sub-method |
MANDATORY | Follow | Throw an exception |
REQUIRES_NEW | Create a new transaction | Create a new transaction |
NOT_SUPPORTED | Pending transaction, run sub-method | No transaction, run sub-method |
NEVER | Throws | No execution method affairs sub |
NESTED | Sub-method exception occurs, roll back the only method of sql child without a parent roll back a transaction methods | Exception occurs, roll back only the sub method of sql, nothing to do with the parent method |
Three common communication behavior:
- REQUIRED
- REQUIRES_NEW
- NESTED
Code propagation behavior of these three tests:
spring使用了save point的技术来让子事务回滚,而父事务不会滚;如果不支持save point,则新建一个事务来运行子事务;
区别点 | RequestNew | Nested |
---|---|---|
传递 | 拥有自己的锁和隔离级别 | 沿用父事务的隔离级别和锁 |
@Transaction自调用失效问题
事务的实现原理是基于AOP,同一个类中方法的互相调用,是自己调用自己,而没有代理对象的产生,就不会用到aop,所以,事务会失效; **解决办法:**通过spring的ioc容器得到当前类的代理对象,调用本类的方法解决; 原创不易,转载请注明出处。