Wildfly和MySQL具有不可重复的读隔离级别

时间:2016-01-22 16:18:40

标签: java hibernate jpa transactions wildfly-9

我正在@Stateless其余资源中的WildFly 9.0.2上实现非可重复读取隔离级别

  1. 线程A正在读取Account实体,打印余额,然后做其他工作(睡眠)。
  2. 线程B进入并读取相同的Account实体,打印余额并通过calculateBalance()方法计算余额,然后更新实体。它再次读取实体并打印出余额。
  3. 线程A然后读取实体并打印出余额。
  4. 根据我对不可重复读取级别的理解,线程B应该阻塞,直到线程A完全完成(退出事务/无状态休息资源)。

    这是打印输出:

    • 主题A:printBalance = 500
    • 主题B:printBalance = 500
    • 主题B:printBalance = 600
    • 主题A:printBalance = 500

    由此我可以看到线程B没有阻塞,即使线程A仍然忙,也可以运行。

    以下是代码:

        @GET
        @Path("/{accountId}/{threadName}")
        public Response calculcateBalance(@PathParam("accountId") Long accountId, @PathParam("threadName") String threadName) {
    
            Account account = em.find(Account.class, accountId);
            printBalance(account,threadName);
    
            if ("ThreadA".equals(threadName)) {
                sleepSeconds(10);
            } else if ("ThreadB".equals(threadName)) {
                account.calculateBalance();
                em.merge(account);
            }
    
        account = em.find(Account.class, accountId);
        printBalance(account,threadName);
    
        return Response.ok().build();
    }
    

    如果我将隔离级别更改为Serializable所有块。

    我对不可重复的理解读错了吗?是否应该在线程A完成之前阻塞线程B?

1 个答案:

答案 0 :(得分:2)

这取决于底层数据库系统。如果您使用的是默认使用2PL的SQL Server,则线程A会在读取该行时获取共享锁,并且线程B将阻止写入该行(直到线程A释放共享锁)。

Oracle,PostgreSQL和MySQL使用MVCC,而Repeatable Read不使用锁定,因为读者不会阻止编写者和编写者不阻止读者。 在MVCC中,检测到异常,如果线程B修改该行,则线程A将检测到该更改并将中止其事务。

所以,在MVCC,anomalies are detected rather than prevented