`
chillwarmoon
  • 浏览: 155348 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Hibernate在应用层对并发事务的控制

阅读更多
Hibernate与事务处理一文中,介绍了事务以及并发事务处理时的问题,和针对于这些问题在数据库层所能做的隔离级别,但是在选择read commit和repeatable read两个隔离级别时,如果考虑到performance和scalability,可以选择一个折衷的方案,也就是在数据库中的隔离级别选择read commit,而通过对应用程序的控制,可以达到repeatable read的效果。Hibernate在程序中控制并发的事务处理上,也有自己的方法,本文在Hibernate与事务处理基础上,对Hibernate的这些并发事务处理方法进行介绍。
数据库隔离级别可以通过设置hibernate的属性文件,来改变数据库默认的隔离级别:
xml 代码
  1. 1:Read umcommited  
  2. 2:Read commited  
  3. 3:Repeatable read  
  4. 4:Serializable  

在这里设置hibernate.connection.isolation=2;但需要注意的是,如果hibernate用在了应用服务器上,该应用服务 器对数据库连接提供了受管理的控制,则这里设置的isolation级别失效,采用的是app server定义的级别,可以通过改变app server的配置来改变该隔离级别。
因为这里设置的隔离级别是read commit,那如果想达到repeatable read,则需要设置version number或者timestamp。

如果某个项目从头到尾开始设计和开发,考虑到事务处理,则在需要并发控制的数据库表字段上,添加和hibernate的version number相对应的字段。例如对Student表的并发控制,则需要在TSTUDENT表上添加STU_VERSION字段,在ORM的映射文件中需要在标识符属性下添加,例如:
java 代码
 
  1. <class name="Student" table="TSTUDENT">  
  2. ...  
  3. <!---->class>  

在Student.java的pojo文件中添加:
java 代码
 
  1. public class Student {  
  2. ....  
  3. private int version;  
  4. ...  
  5. }  

version属性是不能被应用所改变的,所以仅仅提供get方法即可。但是version number是怎样在应用层提供对事务的并发处理机制呢?原理是这样的:在hibernate的事务A(在这里假设事务的范围和Session范围一致,每个Session对应一个persistent context)中,执行每一个DML操作,都会先检查一下对象的version属性,假如从数据库中得到的student实例的version属性是1,此时student已经加载到Session对应的persistent context中,如果对student对象进行改变,在Session.flush()的时候,则将persistent context中的student对象的version属性设置为2,然后在保存student对象时,将对象对应的记录version字段更新为2。
注意的是,如果并发的另一个事务B在事务A进行保存操作之前,已经将version更新为2或者更高值的student存入数据库,那A在保存student之前,需要检查该persistent object对应的记录的version为1(因为在从数据库取得persistent object的时候,version为1)的行的个数,如果行数为0,则抛出 StaleObjectStateException,表明存在其他的事务更新了数据库,那这样的话,A事务的更新操作就不会覆盖B事务的更新操作,达到了避免(3)问题中的second lost update(见Hibernate与事务处理)。
当然避免了second lost update是不够的,因为是不是这样就能够具有repeatable read的隔离级别呢?比较一下read commit和repeatable read的隔离级别的差别,read commit是读事务允许其他事务并发执行,而repeatable read是读事务不允许写事务并发执行,在hibernate中,通过Session对应的persistent context来实现后者,具体是在一个事务A中(假设事务的范围和Session范围一致),读取student对象到persistent context,此时事务B更改了student对象对应的记录并进行持久化,根据数据库的默认隔离级别read commit,那么A事务如果再读取student对象,那就是产生unrepeatable read,其实不然,正是因为hibernate的persistent context,使得A事务再次读取student不是从数据库中读取,而是从当前的Session读取,因此避免了unrepeatable read,同时使得具有类似于数据库隔离级别repeatable read的隔离效果。

当然我们这里假设的是事务的范围和Session范围一致,但是当用户操作中途停留时间过长,则需要将不同的事务在同一conversation下实现,要保证不同事务共用Session可以通过Hibernate的FlushMode来实现。当然也可以保证Session和事务的对应,通过在不同Session中传递detached object来实现。

对于Hibernate在应用层对并发事务的控制方法还有timestamp,pessimistic locking,这里先不做介绍。
分享到:
评论
6 楼 xianyun 2007-07-14  
hibernate使用version可以来解决多个操作同时对数据进行更新的问题,它是通过程序的处理来实现的,是脱离事务的,或者事务级别很低,你要把事务设成repeatable read,反而不好用了(是吧)。它只是用来解决并发更新的问题,与事务隔离级别实现的功能是不完全一样的。
5 楼 chillwarmoon 2007-07-14  
如果有a、b两个对象,在第一个事务中先对a进行了读取,存到了它的缓存中。第二个事务对a、b对象都进行了更新,并提交了事务。然后在第一个事务再次对 a、b进行读取,它可不会知道a已经被其他事务修改了,读的还是缓存中的a,而b在缓存中没有,所以直接读数据库,因为事务是read commited,所以能读到被第二个事务修改的值,那么a、b两个对象的值一个被修改前的一个是被修改后的,是不一致的,可能会影响业务。<br/>
<br/>
你说的对,但是有没有其他方法用hibernate达到应用一层的repeatable read呢?如果使用数据库的repeatable read,那这样的话应用性能会降低。<br/>
如果没有这样的方法,那hibernate又是怎么样保证既不降低应用性能又能很好的处理并发事务呢?
4 楼 Godlikeme 2007-07-14  
对于hibernate在应用一层所作的并发处理是持怀疑态度的,
Lock_mode最终还是落在数据库的transaction上,不同数据库的支持不一样。

version这些处理,觉得只是一些小技巧,但在不同的数据库平台,不同的事务隔离级别体现出来的效果不一样。而且要在业务逻辑中写代码去做判断和处理。
3 楼 xianyun 2007-07-14  
chillwarmoon 写道
xianyun 写道
引用
使得具有类似于数据库隔离级别repeatable read的隔离效果


如果有两个相关的对象,一个在hibernate缓存中,一个不在,有另外一个事务对两个对象都进行的更新,并提交,那还能读到两个对象一致的状态吗?

这个问题就看hibernate的version number是怎么增加的,如果另外的事物对两个对象都进行更新,那么第一个事务所在的persistent context中的detached ojbect就是dirty data,如果第一个事务再次读关联对象时,如果被关联对象是lazy的,那么和数据库中的数据不一样,会产生异常,保证不读取两个不一致的状态。如果被关联对象不是lazy的,已经加载到persistent context中,那么第一个事物两次读取都从persistent context中读,应该是一致的。

你可以做个实验看看。


你怎么就不明白呢,如果有a、b两个对象,在第一个事务中先对a进行了读取,存到了它的缓存中。第二个事务对a、b对象都进行了更新,并提交了事务。然后在第一个事务再次对a、b进行读取,它可不会知道a已经被其他事务修改了,读的还是缓存中的a,而b在缓存中没有,所以直接读数据库,因为事务是read commited,所以能读到被第二个事务修改的值,那么a、b两个对象的值一个被修改前的一个是被修改后的,是不一致的,可能会影响业务。

如果事务级别是Repeatable read呢,不管第二个事务怎么修改数据,在第一个事务中后面读到a、b的值始终是第一次读取a当时时刻的值,也就是第二个事务修改前的值,a与b始终是一致的。

所以说hibernate能实现repeatable read的隔离效果这个说法是有问题的。

其实这和hibernate没有关系,即使在开始读取的时候,不可能一下全部把数据读出来,需要一个一个的读,在这期间也有可能后面的数据被其他事务修改了,导致和前面的不一致,所以,要实现Repeatable read的功能,还是要设置Repeatable read的事务隔离级别。
2 楼 chillwarmoon 2007-07-14  
xianyun 写道
引用
使得具有类似于数据库隔离级别repeatable read的隔离效果


如果有两个相关的对象,一个在hibernate缓存中,一个不在,有另外一个事务对两个对象都进行的更新,并提交,那还能读到两个对象一致的状态吗?

这个问题就看hibernate的version number是怎么增加的,如果另外的事物对两个对象都进行更新,那么第一个事务所在的persistent context中的detached ojbect就是dirty data,如果第一个事务再次读关联对象时,如果被关联对象是lazy的,那么和数据库中的数据不一样,会产生异常,保证不读取两个不一致的状态。如果被关联对象不是lazy的,已经加载到persistent context中,那么第一个事物两次读取都从persistent context中读,应该是一致的。

你可以做个实验看看。
1 楼 xianyun 2007-07-14  
引用
使得具有类似于数据库隔离级别repeatable read的隔离效果


如果有两个相关的对象,一个在hibernate缓存中,一个不在,有另外一个事务对两个对象都进行的更新,并提交,那还能读到两个对象一致的状态吗?


引用
而repeatable read是读事务不允许写事务并发执行
??

相关推荐

    Hibernate教程26_事务并发处理

    在多用户同时访问数据库时,事务并发控制就显得尤为重要,以防数据冲突和不一致。 悲观锁是假设最坏的情况,即每次读取数据时都假设会有其他用户同时尝试修改。因此,悲观锁会在数据读取时立即加上锁,直到事务结束...

    课程hibernate的事务和并发.pdf

    《课程hibernate的事务和并发》主要探讨了在Hibernate框架中如何管理和处理事务以及并发控制。Hibernate作为一款流行的Java ORM(对象关系映射)工具,其事务处理和并发控制策略对于开发高效、稳定的数据库应用至关...

    Hibernate中,利用版本管理机制来控制事务并发

    本文将深入探讨Hibernate如何通过版本管理来控制事务并发,以及它在实际应用中的重要性。 首先,我们需要了解什么是事务并发。在数据库系统中,多个事务可能同时对同一数据进行操作,这种现象称为事务并发。并发...

    Spring Hibernate 事务处理 详细说明

    3. **隔离级别:**包括READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE,它们定义了并发事务之间的可见性。例如,`SERIALIZABLE`是最高的隔离级别,防止脏读、不可重复读和幻读,但性能较低。 4....

    jee事务控制.pdf

    本文将结合Hibernate和JPA标准,深入探讨J2EE持久层设计中遇到的关键问题之一——事务并发访问控制策略。 #### 二、事务并发访问控制策略概述 事务并发访问控制主要包括两方面:同一个系统事务内的并发控制和跨...

    java socket 多线程并发控制 hibernate mysql

    本项目聚焦于使用Java的Socket进行多线程并发控制,并结合Hibernate ORM框架与MySQL数据库进行数据存储。下面将详细阐述这些技术及其应用。 首先,Java Socket是Java提供的用于实现网络上不同计算机间进程通信的...

    J2EE事务并发控制策略总结汇编.pdf

    在J2EE应用中,事务并发控制策略对于确保数据的一致性和完整性至关重要。本文主要围绕J2EE环境下的持久层设计,特别是针对事务并发访问控制进行总结。事务并发访问控制分为两类:同一系统事务内的并发控制和跨系统...

    spring hibernate mysql 事务实例

    在Spring与Hibernate的结合下,MySQL的事务控制可以通过设置不同的隔离级别(如READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE)来优化并发性能和避免数据竞争问题。 在实际开发中,我们还需要...

    学习J2EE事务并发控制策略总结.pdf

    在J2EE应用程序中,事务并发控制策略是确保系统稳定性与数据一致性的重要组成部分。这篇文章主要聚焦于J2EE环境中持久层的设计挑战,特别是如何处理事务的并发访问。它提到了几种常见的并发控制策略,包括乐观锁和...

    第二部分spring+hibernate+jta 分布式事务Demo

    - **DAO层**:数据访问对象(DAO)接口和实现,使用Hibernate的Session进行数据库操作,并在Spring的事务管理下运行。 - **服务层**:业务逻辑处理,通常调用DAO层的方法,并由Spring的事务管理器管理事务。 - **...

    hibernate5--2.数据持久化及事务

    **hibernate5--2.数据持久化及事务** 在Java开发中,数据持久化是将应用程序中的对象状态保存到数据库中的...在实际项目中,结合事务的隔离级别、锁机制以及适当的事务策略,我们可以构建出高效、稳定的数据访问层。

    Hibernate 基于持久层框架的DAO模式应用

    在基于持久层框架的DAO(Data Access Object)模式应用中,Hibernate扮演着核心角色,使得业务逻辑和数据访问逻辑分离,提高了代码的可复用性和可维护性。 1. **DAO模式的理解** DAO模式是一种设计模式,它创建了...

    Web应用中并发控制的实现.pdf

    在实际应用中,选择乐观锁还是悲观锁取决于系统的并发负载、事务的性质以及对性能的要求。对于冲突较少且事务处理时间短的情况,乐观锁更合适,因为它减少了锁定资源的时间,从而提高了系统的并发能力。相反,对于高...

    Hibernate事务缓存

    事务在开始时不锁定数据,而是检查在提交前是否有其他事务修改了数据。 #### 三、Hibernate缓存管理 **1. 缓存的重要性** 缓存能够提高应用的性能,减少对数据库的访问次数。Hibernate支持两种缓存机制:一级缓存...

    Hibernate事务管理.

    然而,如果在服务层(Service layer)或数据访问层(DAO layer)关闭了Session,然后试图在应用层(如视图层)进行懒加载,Hibernate会抛出`session already closed Exception`,因为此时Session已经不再有效。...

    day36 11-Hibernate中的事务:当前线程中的session

    在Hibernate中,Session是与持久化层交互的主要接口,它负责对象的持久化、检索、更新和删除等操作。当涉及到多个数据库操作时,事务管理显得尤为重要,因为它确保了数据的一致性和完整性。在Java中,通常有两种处理...

    SpringAOP整合Hibernate并使用事务(模拟买书的过程)

    在本示例中,我们将探讨如何整合Spring AOP(面向切面编程)与Hibernate ORM框架,并利用它们来实现事务管理,模拟一个简单的买书过程。这个过程将涉及到数据库操作,事务的开始、提交和回滚,以及AOP在处理事务中的...

    spring,struts,hibernate,事务配置

    事务的隔离级别包括READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE,它们影响了并发事务间的可见性和一致性。根据业务场景选择合适的隔离级别是非常重要的。 8. **事务超时设置** 通过`@...

    Spring3.0+Hibernate+Atomikos多数据源分布式事务管理

    **分布式事务的关键挑战**: 分布式事务处理面临的主要挑战包括两阶段提交(2PC)协议的性能瓶颈、事务的回滚与恢复、并发控制以及事务的隔离级别等。Atomikos通过优化的事务算法和智能的回滚策略,尽可能减少了这些...

    Hibernate的多对一和一对多操作实例

    总之,Hibernate的多对一和一对多操作不仅提供了灵活的关联管理,还允许开发者将复杂的数据关系逻辑封装在应用程序中,从而简化数据库设计,提高代码的可读性和可维护性。然而,这也要求开发者对Hibernate的映射机制...

Global site tag (gtag.js) - Google Analytics