慎重!@Transactional事务设置为只读性能下降25%

文摘   2024-11-17 10:30   新疆  

最新实战案例锦集:《Spring Boot3实战案例合集》持续更新,每天至少更新一篇文章,订阅后将赠送文章最后展示的所有MD文档(学习笔记)。

环境:SpringBoot3.2.5



1. 简介

事务管理是一个至关重要的环节,它确保了数据的一致性和完整性。然而,在使用Spring框架的 @Transactional 注解时,有一个设置需要特别慎重对待,那就是事务的只读属性readOnly。

在通过 @Transactional 注解设置事务为只读事务时,你还需要注意,只读事务只支持2种事务的传播特性:REQUIRED 或 REQUIRES_NEW

在MySQL InnoDB引擎中,所有语句都是事务,因此它们可能涉及锁定和快照等机制。然而,对于普通的查询操作,与事务协调相关的一些开销(如用事务ID标记行和其他内部结构)可能是不必要的。这正是只读事务发挥作用的地方。

貌似将事务设置为只读后性能可能会有提升!?但是在最近的一次性能测试中,我发现将 @Transactional 注解的 readOnly 属性设置为 true 后,系统的查询性能下降了约25%。结果挺意外啊。因此,在决定是否将事务设置为只读时,我们需要仔细权衡利弊。

那是不是只读事务就不要使用了呢?非也!接下来我将通过下面几方面来讲解关于只读事务的应用:

  • 解决不可重复读问题

  • 只读事务中进行修改操作

  • 使用JPA时数据自动检查更新问题

  • 读写 / 只读 事务性能测试

  • 只读事务底层执行原理

     

2. 实战案例

准备环境

<dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-data-jpa</artifactId></dependency>

我们会通过jpa来演示上面的第二个问题,所以我们这里需要引入JPA依赖。

实体定义

@Entity@Table(name = "t_person")public class Person {
private Integer id ; private String name ; private Integer age ; // getters, setters}

Repository定义

public interface PersonRepository extends JpaRepository<Person, Integer> {    @Query("select p from Person p where p.id = ?1")  Person queryById(Integer id) ;}

自定义根据ID查询的方法,你也可以用父类的findById。

Controller测试接口

@GetMapping("/{id}")public Person queryPerson(@PathVariable Integer id) {  return this.personService.findById(id) ;}

后续的测试都会基于该接口进行测试。

数据库准备数据

Spring全家桶实战案例源码
spring, springboot, springcloud 案例开发详解
 最新文章