• Hibernate中的事务隔离


    在我们的项目中,老发现程序报告sesssion is closed或者因数据已经被其他事务修改而导致当前事务无法提交,由于系统的运行用户最多也就几十个人,所以考虑使用严格的事务隔离来防止这种类型的问题的出现。或许不能完全解决session is closed的问题(我们怀疑是项目中所使用的jbpm存在bug导致的)。

    1、事务隔离

    事务隔离意味着对于某一个正在运行的事务来说,好像系统中只有这一个事务,其他并发的事务都不存在一样。在大部分情况下,很少使用完全隔离的事务。但不完全隔离的事务会带来如下一些问题。

    更新丢失(Lost Update):两个事务都企图去更新一行数据,导致事务抛出异常退出,两个事务的更新都白费了。
     
    脏数据(Dirty Read):如果第二个应用程序使用了第一个应用程序修改过的数据,而这个数据处于未提交状态,这时就会发生脏读。第一个应用程序随后可能会请求回滚被修改的数据,从而导致第二个事务使用的数据被损坏,即所谓的“变脏”。
     
    不可重读(Unrepeatable Read):一个事务两次读同一行数据,可是这两次读到的数据不一样,就叫不可重读。如果一个事务在提交数据之前,另一个事务可以修改和删除这些数据,就会发生不可重读。
     
    幻读(Phantom Read):一个事务执行了两次查询,发现第二次查询结果比第一次查询多出了一行,这可能是因为另一个事务在这两次查询之间插入了新行。
    针对由事务的不完全隔离所引起的上述问题,提出了一些隔离级别,用来防范这些问题。
     
    读操作未提交(Read Uncommitted):说明一个事务在提交前,其变化对于其他事务来说是可见的。这样脏读、不可重读和幻读都是允许的。当一个事务已经写入一行数据但未提交,其他事务都不能再写入此行数据;但是,任何事务都可以读任何数据。这个隔离级别使用排写锁实现。
     
    读操作已提交(Read Committed):读取未提交的数据是不允许的,它使用临时的共读锁和排写锁实现。这种隔离级别不允许脏读,但不可重读和幻读是允许的。
     
    可重读(Repeatable Read):说明事务保证能够再次读取相同的数据而不会失败。此隔离级别不允许脏读和不可重读,但幻读会出现。
     
    可串行化(Serializable):提供最严格的事务隔离。这个隔离级别不允许事务并行执行,只允许串行执行。这样,脏读、不可重读或幻读都可发生。

    事务隔离与隔离级别的关系如表9-2所示。

    表9-2  事务隔离与隔离级别的关系

    隔 离 级 别

    脏读(Dirty Read)

    不可重读(Unrepeatable read)

    幻读(Phantom Read)

    读操作未提交(Read Uncommitted)

    可能

    可能

    可能

    读操作已提交(Read Committed)

    不可能

    可能

    可能

    可重读(Repeatable Read)

    不可能

    不可能

    可能

    可串行化(Serializable)

    不可能

    不可能

    不可能

    在一个实际应用中,开发者经常不能确定使用什么样的隔离级别。太严厉的级别将降低并发事务的性能,但是不足够的隔离级别又会产生一些小的Bug,而这些Bug只会在系统重负荷(也就是并发严重时)的情况下才会出现。

    一般来说,读操作未提交(Read Uncommitted)是很危险的。一个事务的回滚或失败都会影响到另一个并行的事务,或者说在内存中留下和数据库中不一致的数据。这些数据可能会被另一个事务读取并提交到数据库中。这是完全不允许的。

    另外,大部分程序并不需要可串行化隔离(Serializable Isolation)。虽然,它不允许幻读,但一般来说,幻读并不是一个大问题。可串行化隔离需要很大的系统开支,很少有人在实际开发中使用这种事务隔离模式。

    现在留下来的可选的隔离级别是读操作已提交(Read Committed)和可重读(Repeatable Read)。Hibernate可以很好地支持可重读(Repeatable Read)隔离级别。

    2、在Hibernate配置文件中设置隔离级别

    JDBC连接数据库使用的是默认隔离级别,即读操作已提交(Read Committed)和可重读(Repeatable Read)。在Hibernate的配置文件hibernate.properties中,可以修改隔离级别:

    #hibernate.connection.isolation 4

    在上一行代码中,Hibernate事务的隔离级别是4,这是什么意思呢?级别的数字意义如下。

    1:读操作未提交(Read Uncommitted)
    2:读操作已提交(Read Committed)
    4:可重读(Repeatable Read)
    8:可串行化(Serializable)

    因此,数字4表示“可重读”隔离级别。如果要使以上语句有效,应把此语句行前的注释符“#”去掉:

    hibernate.connection.isolation 4
    

    也可以在配置文件hibernate.cfg.xml中加入以下代码:

     <session-factory>
    …..
    //把隔离级别设置为4
    <property name=” hibernate.connection.isolation”>4</property>
    ……
    </session-factory>


    在开始一个事务之前,Hibernate从配置文件中获得隔离级别的值。

  • 相关阅读:
    两数之和
    数组,链表,跳表
    第二讲:增长全景图
    三数之和
    第一讲:增长的本质
    移动零
    八十忆双亲+师友杂记
    java:从命令行接收多个数字,求和之后输出结果
    编程的精义读后感
    java语言基础第三讲作业
  • 原文地址:https://www.cnblogs.com/jiligalaer/p/4097379.html
Copyright © 2020-2023  润新知