java - Wildfly 和 MySQL 的不可重复读隔离级别

标签 java hibernate jpa transactions wildfly-9

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

  1. 线程 A 正在读取 Account 实体,打印余额,然后执行其他一些工作( sleep )。
  2. 线程 B 进入并读取相同的 Account 实体,打印余额并通过 calculateBalance() 方法计算余额,然后更新实体。它再次读取实体并打印出余额。
  3. 然后线程 A 读取该实体并打印出余额。

根据我对不可重复读取级别的理解,线程 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();
}

如果我将隔离级别更改为可序列化,则所有内容都会阻塞。

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

最佳答案

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

Oracle、PostgreSQL 和 MySQL 使用 MVCC,可重复读取不使用锁定,因为读取器不会阻止写入器,写入器也不会阻止读取器。 在 MVCC 中,会检测到异常,如果线程 B 修改该行,则线程 A 将检测到该更改并中止其事务。

因此,在 MVCC 中,anomalies are detected rather than prevented .

关于java - Wildfly 和 MySQL 的不可重复读隔离级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34951234/

相关文章:

java - Spring 中的 Hibernate 事务管理器配置

java - 在同一方法中使用准备好的语句时如何绕过或避免列更新?

java - 为什么 try-with-resources 不能与字段变量一起使用?

java - 具有备用目标列的 hibernate 映射

java - 如何保存列表中的非常100条记录

java - jpa必须为序列号字段定义一个非只读映射

java - Hibernate 抛出 MultipleBagFetchException - 不能同时获取多个包

java - JPA:具有复合主键和单键的实体映射

java - 如何为我的 java swing 应用程序准备 Mac 安装程序

java - 为什么 mysql 不识别其 LONGTEXT 数据类型上的 Unicode 字符?