Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Wildfly和MySQL的不可重复读取隔离级别_Java_Hibernate_Jpa_Transactions_Wildfly 9 - Fatal编程技术网

Java 使用Wildfly和MySQL的不可重复读取隔离级别

Java 使用Wildfly和MySQL的不可重复读取隔离级别,java,hibernate,jpa,transactions,wildfly-9,Java,Hibernate,Jpa,Transactions,Wildfly 9,我正在一个@Statelessrest资源中的WildFly 9.0.2上实现不可重复读取隔离级别 线程A正在读取帐户实体,打印余额,然后执行一些其他工作(睡眠) 线程B进入并读取相同的帐户实体,打印余额并通过calculateBalance()方法计算余额,然后更新实体。它再次读取实体并打印出余额 线程A然后读取实体并打印出余额 根据我对不可重复读取级别的理解,线程B应该阻塞直到线程A完全完成(退出事务/无状态rest资源) 这是打印件: 螺纹A:printBalance=500 线程B:p

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

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

    这是打印件:

    • 螺纹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 everything blocks


    我对不可重复阅读的理解是否错误?在线程A完成之前,是否应该阻止线程B?

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

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


    所以,在MVCC中,.

    嗨,弗拉德,我认为这正是正在发生的事情。我正在连接MySQL数据库。因此,为了让它检测到实体被更改,我需要在帐户实体上添加
    @Version
    ?我需要MySQL上的任何配置来检测它吗?我认为它没有检测到丢失的更新。你是对的。我有一本书。在中,在第97页,您可以看到一个表,显示MySQL中的可重复读取并不能防止丢失的更新。您需要使用乐观锁定或可序列化,但乐观锁定的伸缩性更好。