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. 加深理解,事務隔離級別研究的是事務之間的關係。而同一個事務中的代碼執行邏輯是沒有所謂的事務隔離級別的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章