Hibernate的事务处理和二级缓存

来源:互联网 发布:点点客 知乎 编辑:程序博客网 时间:2024/05/16 15:24

事务的特性:

事务有严格的定义,需要同时满足4个特性,即原子性、一致性、隔离性、持久性。这4个特性通常称为ACID特性,具体如下:
·原子性(Atomic):表示将事务中所做的操作捆绑成一个不可分割的单元,即对事务所进行的数据修改等操作,要么全部执行,要么全都不执行。
·一致性(Consistancy):表示事务完成时,必须将所有的数据都保持一致。
·隔离性(Isolation):指一个事务的执行不能被其他事务所干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
·持久性(Durability):持久性也称永久性,指一个事务一旦被提交,它对数据库中数据的改变就是永久的。持久后的其他操作或故障不会对其有任何影响。

事务的并发问题:

在实际应用中,数据库是要被多个哟弄个胡所共同访问的。在多个事务同时使用相同的数据时,可能会发生并发的问题,具体如下:
·脏读:一个事务读取到另一个事务未提交的数据
·不可重复读:一个事务对同一行数据重复读取两次,但是却得到不同的结果
·虚读/幻读:事务A在操作过程中进行两次查询,第二次查询的结果包含了第一次中未出现的数据。这时因为在两次查询过程中,有另外一个事务B插入了新数据造成的。
·更新丢失:两个事务都同时更新一行数据,后提交(或撤销)的事务将前面事务提交的数据覆盖了。
·第一类丢失更新:两个事务同时操作同一个数据时,A事务撤销时,吧已经提交的B事务的更新数据覆盖了,这对B事务来说造成了数据丢失
·第二类丢失更新:两个事务同时操作同一个数据时,事务A将修改结果成功提交后,对事务B已提交的修改结果进行了覆盖,对B事务造成了数据丢失

事务的隔离级别:

为了避免事务并发问题的发生,在SQL中,定义4个事务隔离界别,不同的隔离界别对事务的处理不同
·读未提交(Read Uncommitted,1级):一个事务在执行过程中,既可以访问其他事务未提交的新插入的数据,又可以访问未提交的修改数据。如果一个事务已经开始写数据,
则另外一个事务则不允许同时进行写操作,但允许其他事务读取此行数据。此隔离级别可放置丢失更新。
·读已提交(Read Committed,2级):一个事务在执行过程中,既可以访问其他事务成功提交的新插入的数据,又可以访问成功修改的数据。读取数据的事务允许其他事务继续访问该行数据,
但是未提交的写事务将会禁止其他事务访问该行。此隔离级别可防止脏读。
·可重复读取(Repeatable Read,4级):一个事务在执行过程中,可以访问卡事务成功提交的新插入的数据,但不可访问成功修改的数据。读取数据的事务将会禁止写事务(但允许读事务),
写事务则禁止任何其他事务。此隔离级别可有效防止不可重复都和脏读。
·序列化(Serializable,8级):提供严格的事务隔离。它要求事务序列花执行,事务只能一个接着一个地执行,但不能并发执行。此隔离级别可有效防止脏读、不可重复读和幻读。


虽然事务地隔离级别越高,越能保证数据库地完整性和一致性,但并发时越高地级别对性能地影响也越大。在实际开发中,通常将数据库地隔离界别设置为2级,即Read Committed。它技能防止脏读,
又有良好地并发性。虽然这种隔离级别会导致不可重复读、幻读和第二类丢失。但这些可以通过悲观锁和乐观锁来控制。


Hibernate事务配置

使用hibernare.connection.isolation参数来配置事务地隔离级别。
<property name = "hibernate.connection.isolation">2</property>
·1--Read uncommitted 读操作未提交
·2--Read committed读操作已提交
·4--Reapearable read可重复读
·8--Serializable 可串行化(序列化)

Hibernate事务处理方式之悲观锁

当多个事务同时访问数据库中地相同数据时,如果没有采取必要地隔离措施,会导致各种事务地并发问题
悲观锁是指,在每次操作过程中,总是悲观地认为会有其他地事务也会来操作同一数据。因此,在整个数据处理过程中,将会把数据处于锁定状态。
悲观锁具有排他性,一般由数据库来实现。在Hibernata中,可以设定两种锁模式:
·LockMode.UPGRADE:该模式不管缓存中是否存在对象,总是通过select语句到数据库中加载该对象。如果映射文件中设置了版本元素,就执行版本检查,比较缓存中地对象是否与数据库中对象地版本相一致。
如果数据库系统支持悲观锁,就执行select...for update语句,如果不支持,就执行普通地select语句
·LockMode.UPGRADE_NOWAIT:该模式与LockMode.UPGRADE具有同样地功能,是Oracle数据库特有地锁模式,会执行select...for update nowait语句。nowait表示如果执行select语句地事务不成立就获得悲观锁。
它不会等待其他事务释放锁,而是立刻抛出锁定异常。


Hibernate事务处理方式之乐观锁

与悲观锁相比,乐观锁通常认为许多事务同时操作同一个数据的情况很少发生,所以乐观锁不做数据库层次的锁定,而是基于数据库版本的表示实现应用程序级别上的锁定机制。这样既能保证多个事务的并发操作,
又能有效防止第二类丢失更新的发生。
数据库版本表示,是指通过为数据表增加一个“version”字段,实现在读取数据时,将版本号一同读出,之后更新数据时,将此版本号加1.在提交数据时,将现有的版很好与数据表对应记录的版本号进行对比,如果
提交数据的版本号大于数据表中的版本号,则允许更新数据,否则禁止更新数据。


Hibernate的二级缓存

第一级别的缓存时Session级别的缓存,它属于事务范围的缓存。这一级别的缓存由Hibernate管理,一般情况下无需进行干预。第二级缓存是SessionFactory级别的缓存,它属于进程范围的缓存。这一级别的缓存是一个可插拔的缓存插件,
由SessionFactory负责管理。

二级缓存的原理和分类

二级缓存和一级缓存一样,是根据对象的ID来加载和缓存数据。当执行某个查询获得的结果集为实体对象时,Hibernate就会把获得的实体对象按照ID加载到二级缓存中。在访问指定的对象时,首先从一级缓存中查找,
找到就直接使用。找不到则转到二级缓存中查找(必须配置和启动二级缓存)。如果在二级缓存中找到,则直接使用,否则,会查询数据库,将查询结果放到一级和二级缓存中。
SessionFactory的缓存分两类:
·内置缓存:自带的,不可卸载。通常在Hibernate的初始化阶段,Hibernate会把映射元数据和预定义的SQL语句放到SessionFactory的缓存中,映射元数据时映射文件中数据的复制,而预定义SQL语句时Hibernate根据映射元数据推到出来的。该内置缓存是只读的

·外置缓存(二级缓存):一个可排至的缓存插件。默认不会启动。外置缓存中的数据是数据库数据的复制,外置缓存的物理介质可以是内存或硬盘


二级缓存的结构

二级缓存可氛围4类,类级别的缓存、集合级别的缓存、查询缓存和更新时间戳。
·Class Cache Region:类级别的缓存,主要用于存储PO(实体)对象
·Collection Cache Region:类级别的缓存,用于存储集合数据
·Query Cache Region:查询缓存,会缓存一些常用查询语句的查询结果
·Update Timestamps:更新时间戳缓存,该区域存放了与查询结果相关的表在进行插入、更新或删除操作的时间戳。通过更新时间戳缓存区域来判断被缓存的查询结果是否过期。

二级缓存的并发访问策略和供应商

两个并发的事务同时访问持久层缓存的相同数据时,可能会出现各类的并发问题,所以需要采取必要的隔离措施来解决这些问题。在Hibernate的二级缓存中,设定一下4中类型的并发访问策略,来解决这些问题。
·只读型(Read-Only):提供Serializable数据隔离级别,对于从来不会被修改的数据,可以采用这种访问策略
·读写型(Read-Write):提供Read Committed数据隔离级别,对于经常读但是很少修改的数据,可以 采用这种隔离界别。因为可以防止脏读
·非严格的读写(Nonstrict-read-write):不保证缓存与数据库中数据的一致性,提供Read Uncommitted事务隔离级别,对于极少被修改,而且允许脏读的数据,可以采用这种策略
·事务型(Transactional):仅在受管理环境下适用。提供了Repeatable Read事务隔离级别。对于经常读但是很少被修改的数据,可以采用这些隔离界别。可以防止脏读和不可重复读。

Hibernate的二级缓存功能是通过配置二级缓存的插件来实现的,常用的二级缓存插件有如下四种:
·EHCache:可作为进程范围内的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询提供了支持。(支持Read-only,Nonstrict-read-write,Read-Write)
·OpenSymphony OSCache:可作为进程范围内的缓存,存放数据的物理介质可以是内存或硬盘。提供了丰富的缓存数据过期策略,并对Hibernate的查询缓存提供了支持.(支持Read-only,Nonstrict-read-write,Read-Write)
·SwarmCache:可作为集群范围内的缓存,但不支持Hibernate的查询缓存(支持Read-only,Nonstrict-read-write)
·JbossCache:可作为集群范围内的缓存,支持Hibernate的查询缓存。(支持Read-only,Transactional)

1 0