mysql事务隔离级别——可重复读

  1. 不可重复读取问题复现:
    设置事务隔离级别为读取已提交
事务A 事务B
开启事务,设置事务隔离级别为读取已提交
查到5条记录
开启事务,插入一条记录id=6
事务提交
继续查询,查到6条记录

这就出现了一个问题,同一个事务中两次读取的事务条数不一致
更改事务隔离级别解决这个问题

  1. 设置事务隔离级别为可重复读取
事务A 事务B
开启事务,设置事务隔离级别为可以重复读取
查到5条记录
开启事务,插入一条记录id=6
事务提交
继续查询,依然查到5条记录
插入一条记录id=6
事务提交
报错id唯一性校验没有通过
  1. 可重复读取的问题解决了但是又出现新的问题:幻读

  2. mysql的事务隔离级别就是可以重复读取,为了性能做取舍,因为解决幻读需要牺牲数据库性能

  3. 解决幻读问题:mysql事务隔离级别——序列化

  4. 代码演示:

    @Test
      void test() throws InterruptedException {
    
    //    try (SqlSession session = sqlSessionFactory.openSession(TransactionIsolationLevel.READ_COMMITTED)) {
        try (SqlSession session = sqlSessionFactory.openSession(TransactionIsolationLevel.REPEATABLE_READ)) {
          // 开启事务
          List<User> list = session.selectList("getAllUsers");
          assertEquals(5, list.size());
    
          // 等待子线程插入数据
          startThread();
    
          // 等待子线程插入数据
          Thread.sleep(1000);
    
          // 再次读取依然是刚才的数据,说明数据可以重复读取
          List<User> list2 = session.selectList("getAllUsers");
          assertEquals(5, list2.size());
    
    
          /**
           *
           * 可重复读的问题解决了,但是又出现了幻读问题
           *
           * sqlSessionFactory.openSession(TransactionIsolationLevel.REPEATABLE_READ)
           * 出现幻读问题
           * 子线程插入数据成功
           * 主线程事务回滚
           */
          try {
            insertUser(session, "user66666");
          } catch (Exception e) {
            e.printStackTrace();
          }
    
        }
    
        try (SqlSession session = sqlSessionFactory.openSession(TransactionIsolationLevel.REPEATABLE_READ)) {
          User user = session.selectOne("getUsersById", 6);
          assertEquals("user6", user.getName());
        }
    
      }
    
  5. 通过代码调试可以对事务隔离级别有深刻的理解:
    gituhub代码下载

你可能感兴趣的:(mybatis探究,java,mybatis,编程语言,mysql,mysql优化)