Spring的@Transactional在MySQL不同事务隔离级别的表现形式?

背景
  1. 同一个事务中,MySQL数据库隔离级别为可重复读读提交读未提交串行化。对需要插入的一条数据进行很多其他操作,会出现怎样的情况呢?

  2. 同一个事务中,研究事务隔离级别是没有任何意义的。可重复读,读提交,读未提交,串行化都可以对同一条数据反复地进行操作。

  3. 起两个事务,在数据库中事务隔离级别是:可重复读,读未提交,读提交,又是怎样的表现形式呢?

过程

Spring使用@Transactional且是同一个事务中

  • 可重复读

    在数据库中执行如下:select @@transaction_isolation ;

    得到数据库的隔离级别是:REPEATABLE-READ

    java代码

@Service
@Transactional(readOnly = true)
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentMapper studentMapper;

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void insert(Student student) {
        studentMapper.insert(student);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Student selectByName(String name) {
        return studentMapper.selectByName(name);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Student selectById(Integer id) {
        return studentMapper.selectById(id);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void update(Student sara) {
        studentMapper.update(sara);
    }

}

测试代码:

	@Test
    public void test1() {
        Student sara = Student.builder()
                .name("Test1")
                .age(22)
                .createTime(new Date())
                .status(1).build();
        studentService.insert(sara);
        Student student1 = studentService.selectByName(sara.getName());
        System.out.println("name: " + student1.getName());

        student1.setName("Test2");
        studentService.update(student1);
        Student student2 = studentService.selectByName("Test2");
        System.out.println("name: " + student2.getName());

    }

测试结果
在这里插入图片描述

过程分析
Spring类上的@Transactional注解是只读的,方法上的注解不是只读的,但是要求必须在事务中执行。此时没有任何异常出现,因此也不需要什么回滚操作。

当代码执行insert的时候,会启动一个事务,后续的方法selectByName, update, selectByName都不会另启一个事务。这四个方法都在同一个事务中执行。

测试证明:在同一个事务中,对同一条数据进行先插入,后查询,再更新,再查询,都是可行的。

Spring使用@Transactional且是不同事务中

  • 可重复读 数据事务隔离级别是可重复读

    一个事务A代码:在打印语句处,点上debug

     	@Transactional(propagation = Propagation.REQUIRED)
        @Override
        public void insert(Student student) {
            studentMapper.insert(student);
            System.out.println("aaaaa");
        }
    

    测试代码:

     	@Test
        public void test2() {
            Student sara = Student.builder()
                    .name("Test1")
                    .age(22)
                    .createTime(new Date())
                    .status(1).build();
            studentService.insert(sara);
        }
    

    另一个事务B代码: 根据姓名为Test1进行查询

    	@Transactional(propagation = Propagation.REQUIRED)
        @Override
        public Student selectByName(String name) {
            return studentMapper.selectByName(name);
        }
    

    测试代码:

    	@Test
        public void test3() {
            Student student1 = studentService.selectByName("Test1");
            System.out.println("name: " + student1.getName());
        }
    

    测试结果:
    事务A启动,由于在事务方法内中打上debug,此方法未执行完成,因此事务是不会提交的。
    事务B启动,去查询事务A插入的数据,结果是查询为空。

  • 读未提交(数据库的事务隔离级别),又是怎样的表现形式呢?
    在数据库中执行如下:
    – 设置read uncommitted级别:
    set session transaction isolation level read uncommitted;
    set global transaction isolation level read uncommitted;

    测试过程与上面一样:
    因为是读未提交,当事务A代码卡在打印语句处,查询数据库就已经有数据了。
    因此,此时执行查询事务操作,能够查询到此数据。

  • 读提交(数据库的事务隔离级别),又是怎样的表现形式呢?
    – 设置read committed级别:
    set session transaction isolation level read committed;
    set global transaction isolation level read committed;

    测试过程与上面一样:
    因为是读提交,当事务A代码卡在打印语句处。
    此时执行查询事务B操作,不能查询到此数据。

小结
  1. 查询 MySQL实例隔离级别指令 select @@transaction_isolation, @@tx_isolation;

  2. 记录MySQL设置隔离级别指令

    – 设置read uncommitted级别:
    set session transaction isolation level read uncommitted;
    set global transaction isolation level read uncommitted;

    – 设置read committed级别:
    set session transaction isolation level read committed;
    set global transaction isolation level read committed;

    – 设置repeatable read级别:
    set session transaction isolation level repeatable read;
    set global transaction isolation level repeatable read;

    – 设置serializable级别:
    set session transaction isolation level serializable;
    set global transaction isolation level serializable;

  3. 记录Spring的注解@Transactional在不同的数据库事务隔离级别的表现形式。

  4. 加深理解,事务隔离级别研究的是事务之间的关系。而同一个事务中的代码执行逻辑是没有所谓的事务隔离级别的

你可能感兴趣的:(事务和锁,Spring,Transactional,MySQL事务,事务隔离级别,Spring与Mysql事务)