【问题标题】:Why I can't effect READ_UNCOMMITTED Isolation in my test为什么我不能在我的测试中影响 READ_UNCOMMITTED 隔离
【发布时间】:2018-07-19 23:03:56
【问题描述】:

我只是想用spring data jpa和spring boot来测试spring对Transactional annotation的支持。
这是我的控制器方法。

@GetMapping(path = "testreaduncommit")
public void testReadUnCommit()
{
    new Thread(new Runnable() {
        @Override
        public void run() {
        testService.testReadUncommitted1();
        }
    }).start();
    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    testService.testReadUncommitted2();
}

还有我的服务工具

@Override
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void testReadUncommitted1() {
    log.info("testUncommit1 begin");
    User u=userRepository.findOne(1L);
    u.setUserPwd("654321");
    userRepository.save(u);
    log.info("testUncommit1 sleep");
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    log.info("testUncommit1 will be commit");
}

@Override
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void testReadUncommitted2() {
    log.info("testUncommit2 begin");
    User u=userRepository.findOne(1L);
    log.info(u);
}


结果是:
testUncommit1 开始;
testUncommit1 睡眠;
testUncommit2 开始;
用户(userId=1, userName=testuser, userPhone=15888888888, userStatus=2, userPwd=123456);
testUncommit1 将被提交;
所以我想知道为什么注释@Transactional的属性'isolation = Isolation.READ_UNCOMMITTED'不起作用,我认为结果应该是userPwd = 654321,因为READ_UNCOMMITTED应该发生'脏读'。
而且我曾尝试添加userRepository.flush();,它影响了但是在我将隔离级别更改为SERIALIZABLE之后,也发生了脏读,为什么?
我的数据库是Mysql。

所以当我添加 flush(); 我改变了方法的隔离;

@Override
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void testReadCommit1() {
        log.info("testReadCommit1 begin");
        User u=userRepository.findOne(1L);
        u.setUserPwd("654321");
        userRepository.save(u);
        userRepository.flush();
        log.info("testReadCommit1 sleep");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("testReadCommit1 will be commit");
    }

    @Override
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void testReadCommit2() {
        log.info("testUncommit2 begin");
        User u=userRepository.findOne(1L);
        log.info(u);
    }

结果是:
用户(userId=1, userName=testuser, userPhone=15888888888, userStatus=2, userPwd=654321)
为什么 SERIALIZABLE 不能阻止脏读?

【问题讨论】:

  • 你用的是什么数据库?
  • Mysql数据库
  • 你必须调用flush,因为save不执行SQL语句。请更新您的问题,我可以理解添加刷新后您的问题是什么。
  • 我已经编辑了问题,感谢您的帮助
  • 请正确编辑您的问题。添加 flush() 后 READ_UNCOMMITED 不起作用,但 SERIALIZE 不起作用?

标签: java spring spring-data-jpa spring-transactions transactional


【解决方案1】:

以下 API 文档称调用 flush() 会将所有待处理的更改刷新到数据库。因此,当您的 testReadCommit2() 方法在 3 秒后运行时,它不会读取脏记录。

https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html#flush--

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    相关资源
    最近更新 更多