Spring transaction propagation behavior practice

An overview of the

The Spring framework provides a standard implementation of transaction management, and transactions can be declared and configured through annotations or XML files.

Decoupled service invocations by asynchronous events can improve program response times and avoid transaction problems caused by transaction propagation behavior.

Based on the actual background of an e-commerce platform, this paper decouples nested transactions by asynchronous events and thread pool to improve program concurrency performance. In order to facilitate the problem analysis and solution understanding, it also explains Spring transaction management, and highlights several different transaction propagation behaviors.

Business Tips

What is a transaction? Simply put, a transaction is a logical set of operations that either all or none of them execute.

What is transaction management? The so-called transaction management is actually “according to the given transaction rules to perform the commit or rollback operation of the transaction”.

The implementation of transactions relies heavily on transaction log files (undo log and redo log). The transaction log is a separate file from the database file. It stores all changes made to the database and all records inserts, updates, deletions, commits, rollbacks, and database schema changes. Transaction logs are an important component of backup and recovery.

The order failed to go out

Before the delivery of the parcel of the order, the delivery instruction will be sent to the mall, which contains the express information of the parcel delivery, so that the sales platform can display the tracking information of the parcel delivery; At the same time, in order to prevent the front end from being oversold or placing repeated orders, the order has been cancelled, and it will judge whether the order can be delivered according to the return status of the front end mall.

The system interaction process is as follows. Between the front-end sales platform and WMS (Warehouse management system), there is a unified OMS (Order management system) to manage sales orders and transfer data.

After receiving the outbound information, the current sales platform will perform the following verification and operations:

To prevent an exception when calling the notification service from leaving the library, the code that calls the notification service is wrapped in a try-catch statement.

However, the following anomalies still occur in the delivery of some orders, and the delivery fails:

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionMa nager.java:873) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.jav a:710) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSu pport.java:534) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.ja va:305)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
Copy the code

Transaction rolled back because it has been marked as rollback-only When the calling party committed the transaction, it could not commit because it was marked rollback-only.

Propagation mechanism for Spring transactions

Let’s talk more about the propagation mechanism of Spring transactions.

Spring’s @Transactional annotation can be used to declare that methods support transactions, which are controlled by the underlying AOP approach.

The Propagation attribute in the @Transactional annotation can be used to specify the Propagation behavior of a transaction.

/**
    * The transaction propagation type.
    * <p>Defaults to {@link Propagation#REQUIRED}.
    * @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior()
    */
Propagation propagation(a) default Propagation.REQUIRED;
Copy the code

TransactionDefinition includes the following constants that represent propagation behavior:

  • TransactionDefinition. PROPAGATION_REQUIRES_NEW: create a new transaction, if a transaction exists, suspending the current transaction. Current transactions are not supported.

  • TransactionDefinition. PROPAGATION_NOT_SUPPORTED: run way of transaction, if a transaction exists, suspending the current transaction. Current transactions are not supported.

  • TransactionDefinition. PROPAGATION_NEVER:

Runs nontransactionally and throws an exception if a transaction currently exists. Current transactions are not supported.

  • TransactionDefinition. PROPAGATION_REQUIRED: if a transaction exists, then join the transaction; If there is no transaction currently, a new transaction is created. Support for current transactions.

  • TransactionDefinition. PROPAGATION_SUPPORTS: if a transaction exists, then join the transaction; If there is no transaction currently, it continues in a non-transactional manner. Support for current transactions.

  • TransactionDefinition. PROPAGATION_MANDATORY: if a transaction exists, then join the transaction; If there is no transaction currently, an exception is thrown. Support for current transactions.

  • TransactionDefinition. PROPAGATION_NESTED: if a transaction exists, then create a transaction for the current affairs of nested transactions to run; If no current affairs, the value of equivalent to the TransactionDefinition. PROPAGATION_REQUIRED. Support for current transactions.

It is important to point out that the previous six transaction propagation behaviors were introduced by Spring from EJBs and share the same concept. PROPAGATION_NESTED is unique to Spring. A nested transaction is not an independent transaction (if any), depending on the existence of an external transaction. An internal transaction can be committed only by an external transaction, and nested subtransactions cannot be committed independently. Nested transactions are easy to understand if you are familiar with the concept of savepoints in JDBC. A nested subtransaction is an application of savepoints. A transaction can contain multiple savepoints, each nested subtransaction. In addition, rollback of an external transaction also results in rollback of nested child transactions.

A solution that leverages transactional propagation behavior

Based on the transaction propagation behavior described above, set the propagation behavior of a transaction to PROPAGATION_REQUIRES_NEW, so that the current and called transaction are two different transactions that can be committed or rolled back separately.

In outer transaction after catch exceptions, execute the following code will output false, show the inner transaction rollback is not transmitted to the outer transaction: TransactionAspectSupport. CurrentTransactionStatus () isRollbackOnly ()

If the inner transaction executes the following code, it will return true, indicating that the inner transaction is a new transaction, and the current transaction will be suspended when the inner transaction executes: TransactionAspectSupport.currentTransactionStatus().isNewTransaction()

This solves the problem of a try-catch block throwing an exception that causes the current transaction to fail to commit due to transaction propagation behavior.

Leverage multi-threaded solutions

We know that transactions are independent between threads. For businesses such as sending notification messages, it is appropriate to throw events and then process them through asynchronous listeners.

The process is as follows:

As for the implementation mode of the Event model, it can be distributed Zookeeper, Redis and MQ, or non-distributed Guava Event Bus and Spring Event, and can be selected according to actual needs. The core principle is still the publish and subscribe model.

Refer to the link

Aspects of a database transaction

Probably the most beautiful explanation of Spring transaction management

Transaction must be known and will be done