background

Spring’s @Transactional annotation makes it easy to implement transaction control for database operations. This article introduces a nested transaction issue we encountered last week and discusses how the timing of a nested transaction can affect subsequent operations.

Transaction usage on the service invocation chain

In A call chain, method A calls method B, and there are database operations in method A and B, roughly the pseudo-code is as follows:

Public void A() {1, select * from B; 2, select * from B; } public void B {} public void B {}Copy the code

Here we discuss where the transaction annotations are added and the impact on steps 5 and 6.

Case 1: Only add transaction to A, all operations are in the same transaction, the data of step 5 and step 6 depend on the data of step 4, and the data is consistent. The @Transactional annotation annotates a process in which all DAO operations are in the same transaction. For the Propagation.REQUIRES_NEW transaction, prior database writes are visible to subsequent reads.

Case 2: There are transactions on both A and B, and the data is inserted into A table after the method B is called in Step 4. The data cannot be found in step 5, but the record is deleted when the method 6 is deleted, indicating that the transaction of method B is committed during the write operation. In this case, to make step 5 immediately read the data inserted by method B, you can modify the SQL and force the commit by adding for UPDATE.

Case 3: B does not use the transaction annotation, but commits the insert manually using the TransactionTemplate, and the subsequent operation data remains consistent.

The revelation of

The reason why A new transaction is added to method B is to prevent method B’s operation from being affected by method A’s exception. However, if the two data are query dependent, the query operation will not commit B’s transaction, thus causing data inconsistency problem.