"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > When and Why Should You Adjust the Default Isolation and Propagation Parameters in @Transactional?

When and Why Should You Adjust the Default Isolation and Propagation Parameters in @Transactional?

Published on 2024-11-06
Browse:820

When and Why Should You Adjust the Default Isolation and Propagation Parameters in @Transactional?

Isolation and Propagation Parameters in @Transactional

In Spring's @Transactional annotation, two critical parameters define the behavior of database transactions: isolation and propagation. This article explores when and why you should consider adjusting their default values.

Propagation

Propagation defines how transactions relate to each other. Common options include:

  • REQUIRED: Runs the code within an existing transaction or creates a new one if none exists.
  • REQUIRES_NEW: Always creates a new transaction, suspending any existing ones.

Default Value: REQUIRED

Isolation

Isolation defines the data contract between transactions. It prevents certain data inconsistencies by specifying the level of visibility into data changes made by other transactions. Key isolation levels are:

  • READ_UNCOMMITTED: No protection against dirty reads.
  • SERIALIZABLE: Strongest isolation, ensuring no data conflicts.

Default Value: Varies depending on the database (e.g., REPEATABLE_READ for MariaDB)

Real-World Example

Consider the issue of dirty reads, where a transaction can read uncommitted changes made by another transaction.

                                       Thread 1          Thread 2
                                               |              |
                                             Write(x)           |
                                               |              |
                                               |             Read(x)
                                               |              |
                                             Rollback           |
                                                 |             |
                                                   Value (x) is now dirty (incorrect)

In this scenario, to prevent dirty reads, you could set the isolation level to READ_COMMITTED and the propagation level to REQUIRED. This combination ensures that transactions only read data that has been committed by other transactions.

Customizing Transactions

In the following example, the provideService method always runs within a new transaction, ensuring that any changes made by other concurrent tasks do not interfere with its execution:

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void provideService() {
    repo1.retrieveFoo();
    repo2.retrieveFoo();
}

Testing Transaction Behavior

To verify the behavior of different propagation levels, you can use a Java test:

@Test
public void testProvideService() {
    TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
    fooService.provideService();
    transactionManager.rollback(status);
    // Assert repository values are unchanged ...
}

With REQUIRES_NEW, fooService.provideService() would not be rolled back since it operated within a separate transaction. With REQUIRED, everything would be rolled back.

Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3