Hibernate之事务(transaction)

(一)事务(transaction):一组命令,要么都执行,要么都不执行。

(二)事务的特性:ACID    Atomicity:原子性    Consistency:一致性    Isolation:隔离性     Durability:持久性

(三)事务并发时可能出现的问题:

1、dirty read (脏读):一个事务可能会读取另一个事务没有提交的更新数据。
2、unrepeated read (不可重复读):一个事务两次读取同一行数据,结果得到不同状态结果,正如这中间正好有另一个事务更新了该数据,两次结果相异,不可信任。

3、second lost updates(第二类丢失更新):是不可重复读的特殊情况,如果两个事务都读取同一行,然后两个都进行写操作,并提交,第一个事务所做的改变就会丢失。(例如:两个事务都查询同一个账户,账户余额都是1000,都向里面存入100,并提交显示1100.其实应该是1200。这就造成了第一个事务提交数据的丢失)

4、phantom read(幻读):一个事务执行两次查询,第二次查询比第一次多出或少一些数据,造成两次结果不一致。这是另一个事务在这两次查询中间插入或者删除了数据造成的。

5、lost updates(第一类丢失更新):在完全未隔离事务的情况下,两个事务更新同一条数据资源,其中一个事务异常终止回滚,造成另一个已完成更新事务的数据也同时丢失。(只要数据库支持事务,就不会出现第一类丢失更新:事务的本质就是要么都成功,要么都失败,出现异常就都失败)

(四)对于事务并发问题的解决方法:

为了解决数据库事务并发运行时的各种问题数据库系统提供四种事务隔离级别

1. Read Uncommited 可读取未提交的数据 :会出现 dirty Read ,unrepeated Read , phantom Read问题

2. Read Commited 可读取已提交的数据:不会出现dirty Read,但是会出现unrepeated Read ,phantom Read问题(比较常用)

4. Repeatable Read 可重复读(通过加锁机制,给数据加锁,该事务没有完成,其他事务无法操作改数据)

8. Serializable 串行化:效率比较低,但是可以解决所有并发问题,几乎不使用。

Hibernate事务的隔离级别是通过设置 hibernate.connection.isolation=2 即可。

至于隔离级别的序号为(1,2,4,8):是因为进制问题,1(0000) 2(0010) 4(0100) 8(1000) 二进制的移位效率非常高。

(五)并发的控制

1.对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读,而且具有较好的并发性能。
2.每个数据库连接都有一个全局变量@@tx_isolation,表示当前的事务隔离级别。JDBC数据库连接使用数据库系统默认的隔离级别。
3.在hibernate的配置文件中可以显示地设置隔离级别。每一种隔离级别对应着一个正整数

4.需要注意的是,在受管理环境中,如果Hibernate使用的数据库连接来自于应用服务器提供的数据源,Hibernate不会改变这些连接的事务隔离级别。在这种情况下,应该通过修改应用服务器的数据源配置来修改隔离级别。

5.当数据库系统采用Red Committed隔离级别时,会导致不可重复读和第二类丢失更新的并发问题,在可能出现这种问题的场合。可以在应用程序中采用悲观锁或乐观锁来避免这类问题。


悲观锁(解决repeatable read 问题)

     在该事务期间,无论其他事务对该数据操作或者不操作,都会对数据加锁(数据库提供的锁),使其他事务都无法对该数据修改。
  正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
  一个典型的依赖数据库的悲观锁调用:select * from account where name=”Erica” for update这条 sql 语句锁定了 account 表中所有符合检索条件( name=”Erica” )的记录。本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。悲观锁,也是基于数据库的锁机制实现。
  在Hibernate使用悲观锁十分容易,但实际应用中悲观锁是很少被使用的,因为它每次发送的SQL语句都会加上"for update"用于告诉数据库锁定相关数据,大大限制了并发性:
乐观锁
  相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个"version"字段来实现。
  乐观锁的工作原理:读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
Hibernate为乐观锁提供了3中实现:
1. 基于version
2. 基于timestamp




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一位远方的诗人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值