Hibernate 事物隔离级别 深入探究

目录

一、数据库事务的定义

二、数据库事务并发可能带来的问题

三、数据库事务隔离级别

四、使用Hibernate设置数据库隔离级别

五、使用悲观锁解决事务并发问题

六、使用乐观锁解决事务并发问题

 

  Hibernate事务与并发问题处理(乐观锁与悲观锁)

一、数据库事务的定义

  数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。 

  1. 原子性(atomic),事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行

  2. 一致性(consistent),事务在完成时,必须使所有的数据都保持一致状态。

  3. 隔离性(insulation),由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。

  4. 持久性(Duration),事务完成之后,它对于系统的影响是永久性的。

二、数据库事务并发可能带来的问题 

  如果没有锁定且多个用户同时访问一个数据库,则当他们的事务同时使用相同的数据时可能会发生问题。由于并发操作带来的数据不一致性包括:丢失数据修改、读”脏”数据(脏读)、不可重复读、产生幽灵数据:

假设数据库中有如下一张表:

  1. 第一类丢失更新(lost update): 在完全未隔离事务的情况下,两个事物更新同一条数据资源,某一事物异常终止,回滚造成第一个完成的更新也同时丢失。

  在T1时刻开启了事务1,T2时刻开启了事务2,在T3时刻事务1从数据库中取出了id="402881e535194b8f0135194b91310001"的数据,T4时刻事务2取出了同一条数据,T5时刻事务1将age字段值更新为30,T6时刻事务2更新age为35并提交了数据,但是T7事务1回滚了事务age最后的值依然为20,事务2的更新丢失了,这种情况就叫做"第一类丢失更新(lost update)"。

  2. 脏读(dirty read):如果第二个事务查询到第一个事务还未提交的更新数据,形成脏读。

  在T1时刻开启了事务1,T2时刻开启了事务2,在T3时刻事务1从数据库中取出了id="402881e535194b8f0135194b91310001"的数据,在T5时刻事务1将age的值更新为30,但是事务还未提交,T6时刻事务2读取同一条记录,获得age的值为30,但是事务1还未提交,若在T7时刻事务1回滚了事务2的数据就是错误的数据(脏数据),这种情况叫做" 脏读(dirty read)"。

  3. 虚读(phantom read):一个事务执行两次查询,第二次结果集包含第一次中没有或者某些行已被删除,造成两次结果不一致,只是另一个事务在这两次查询中间插入或者删除了数据造成的。

  在T1时刻开启了事务1,T2时刻开启了事务2,T3时刻事务1从数据库中查询所有记录,记录总共有一条,T4时刻事务2向数据库中插入一条记录,T6时刻事务2提交事务。T7事务1再次查询数据数据时,记录变成两条了。这种情况是"虚读(phantom read)"。

  4. 不可重复读(unrepeated read):一个事务两次读取同一行数据,结果得到不同状态结果,如中间正好另一个事务更新了该数据,两次结果相异,不可信任。

  在T1时刻开启了事务1,T2时刻开启了事务2,在T3时刻事务1从数据库中取出了id="402881e535194b8f0135194b91310001"的数据,此时age=20,T4时刻事务2查询同一条数据,T5事务2更新数据age=30,T6时刻事务2提交事务,T7事务1查询同一条数据,发现数据与第一次不一致。这种情况就是"不可重复读(unrepeated read)"。

  5. 第二类丢失更新(second lost updates):是不可重复读的特殊情况,如果两个事务都读取同一行,然后两个都进行写操作,并提交,第一个事务所做的改变就会丢失。

  在T1时刻开启了事务1,T2时刻开启了事务2,T3时刻事务1更新数据age=25,T5时刻事务2更新数据age=30,T6时刻提交事务,T7时刻事务2提交事务,把事务1的更新覆盖了。这种情况就是"第二类丢失更新(second lost updates)"。

 

三、数据库事务隔离级别

为了解决数据库事务并发运行时的各种问题数据库系统提供四种事务隔离级别:
1. Serializable 串行化
2. Repeatable Read 可重复读
3. Read Commited 可读已提交
4. Read Uncommited 可读未提交

隔离级别与并发性能的关系: 

每一个隔离级别可以解决的问题:

 

四、使用Hibernate设置数据库隔离级别

在Hibernate的配置文件中可以显示的配置数据库事务隔离级别。每一个隔离级别用一个整数表示:

8 - Serializable 串行化
4 - Repeatable Read 可重复读
2 - Read Commited 可读已提交
1 - Read Uncommited 可读未提交

在hibernate.cfg.xml中使用hibernate.connection.isolation参数配置数据库事务隔离级别。

 

五、使用悲观锁解决事务并发问题

  悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。

  一个典型的依赖数据库的悲观锁调用:select * from account where name=”Erica” for update这条 sql 语句锁定了 account 表中所有符合检索条件( name=”Erica” )的记录。本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。悲观锁,也是基于数据库的锁机制实现。

在Hibernate使用悲观锁十分容易,但实际应用中悲观锁是很少被使用的,因为它大大限制了并发性:

图为Hibernate3.6的帮助文档Session文档的get方法截图,可以看到get方法第三个参数"lockMode"或"lockOptions",注意在Hibernate3.6以上的版本中"LockMode"已经不建议使用。方法的第三个参数就是用来设置悲观锁的,使用第三个参数之后,我们每次发送的SQL语句都会加上"for update"用于告诉数据库锁定相关数据。

LockMode参数选择该选项,就会开启悲观锁。

  T1,T2时刻取款事务和转账事务分别开启,T3事务查询ACCOUNTS表的数据并用悲观锁锁定,T4转账事务也要查询同一条数据,数据库发现该记录已经被前一个事务使用悲观锁锁定了,然后让转账事务等待直到取款事务提交。T6时刻取款事务提交,T7时刻转账事务获取数据。

 

六、使用乐观锁解决事务并发问题

  相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个"version"字段来实现。
  乐观锁的工作原理:读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

Hibernate为乐观锁提供了3中实现:

1. 基于version

2. 基于timestamp

3. 为遗留项目添加添加乐观锁 

配置基于version的乐观锁:

复制代码
复制代码
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" table="people">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>

<!-- version标签用于指定表示版本号的字段信息 -->
<version name="version" column="version" type="integer"></version>

<property name="name" column="name" type="string"></property>

</class>
</hibernate-mapping>
复制代码
复制代码

配置基于timestamp的乐观锁:

复制代码
复制代码
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" table="people">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>

<!-- timestamp标签用于指定表示版本号的字段信息 -->
<timestamp name="updateDate" column="updateDate"></timestamp>

<property name="name" column="name" type="string"></property>

</class>
</hibernate-mapping>
复制代码
复制代码

遗留项目,由于各种原因无法为原有的数据库添加"version"或"timestamp"字段,这时不可以使用上面两种方式配置乐观锁,Hibernate为这种情况提供了一个"optimisitic-lock"属性,它位于<class>标签上:

复制代码
复制代码
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" table="people" optimistic-lock="all">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>

<property name="name" column="name" type="string"></property>
</class>
</hibernate-mapping>
复制代码
复制代码

将该属性的值设置为all,让该记录所有的字段都为版本控制信息。

转载于:https://www.cnblogs.com/jiligalaer/p/3990369.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/258164.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql 无论输入什么都是现实 not found_NotAPanda

前言面试竞争力越来越大&#xff0c;是时候撸一波Vue和React源码啦&#xff1b;本文从20个层面来对比Vue和React的源码区别&#xff1b;如果需要了解API的区别&#xff0c;请戳&#xff1a;Vue 开发必须知道的 36 个技巧React 开发必须知道的 34 个技巧文章源码&#xff1a;请戳…

这五张PPT告诉你,如何打造无人驾驶“最强大脑”

“英特尔在谈无人驾驶&#xff0c;会成为汽车制造商吗?NO!我们要为无人驾驶提供从车、连接到云的‘最强大脑’。” 在昨天于北京举行的英特尔无人驾驶分享会上&#xff0c;英特尔无人驾驶事业部中国区市场总监徐伟杰在主旨演讲中开门见山。 这也是英特尔无人驾驶事业部去年11月…

python的datetime举例_Python datetime模块的使用示例

1、获取当前年月日时分秒# -*- encodingutf-8 -*-import datetimenow datetime.datetime.now()print("now:{}".format(now))year now.yearprint("year:{}".format(year))month now.monthprint("month:{}".format(month))day now.dayprint(&q…

vs2015 去除 git 源代码 绑定,改成向tfs添加源码管理

除了下文的方法是将源码管理从git改成tfs之外&#xff0c;还要做以下几步即可 向tfs添加源码 打开源码管理(管理连接)&#xff0c;双击打开你要向其中添加的tfs连接选中该解决方案&#xff0c;右键 将解决方案添加到源码管理嵌入完毕vs2015 去除 git 源代码 绑定 第一次碰到这个…

《日志管理与分析权威指南》一2.3 良好日志记录的标准

本节书摘来华章计算机《日志管理与分析权威指南》一书中的第2章 &#xff0c;第2.3节&#xff0c;&#xff08;美&#xff09; Anton A. Chuvakin Kevin J. Schmidt Christopher Phillips 著 姚 军 简于涵 刘 晖 等译更多章节内容可以访问云栖社区“华章计算机”公众号查…

Python【01】【基础部分】- A

一、WHATS PYTHON ? 1、python 简介 Python&#xff08;英语发音&#xff1a;/ˈpaɪθən/&#xff09;, 是一种面向对象、解释型计算机程序设计语言&#xff0c;由Guido van Rossum于1989年发明&#xff0c;第一个公开发行版发行于1991年。Python是纯粹的自由软件&#xff0…

Finished yeah!

终于到了最后的博客阶段&#xff0c;这时候才知道博客此时此刻是多么的惬意&#xff0c;它成了书写心声的自由平台&#xff01;耗时一天完成这作业说起来也是蛮辛苦的&#xff0c;编译器需要新装&#xff0c;IDE需要熟悉&#xff0c;当然最主要的是之前浅入浅出的C功底在此次作…

Tomcat性能调优

1、集成apache 虽然Tomcat也可以作web服务器&#xff0c;但是处理静态html的速度比不上apache&#xff0c;且其作为web服务器的功能远不如Apache&#xff0c;因此把apache和tomcat集成起来&#xff0c;讲html和jsp功能部分进行明确的分工&#xff0c;让tomcat只处理jsp部分&…

河南推出近万亿PPP投资计划 郑州实现智慧城市全覆盖

1 近万亿PPP项目启动 眼下&#xff0c;国内财经新闻的热点聚焦在PPP开发上&#xff0c;这与PPP支撑国内经济平衡运行的一支强劲力量正被政府看好。就连二级市场也出现了PPP概念的抢筹现象。 9月27日&#xff0c;股市再一次遭遇抛售&#xff0c;大盘创出阶段性新低&#xff0c;然…

Loadrunner多服务器连接问题

今天用想增加一个压力机,在服务器管理列表里怎么也连不上,后来解决方法如下:1. 关闭所有loadrunner组件,并手动结束lr_开头的进程2.找到惠普loadrunner安装目录(C:\Program Files\HP\LoadRunner\bin),手动运行magentproc.exe即可最新内容请见作者的GitHub页&#xff1a;http://…

物联网安防技术融合在细分领域的应用分析

物联网的核心是业务和应用的创新。物联网技术与智能化技术的深度融合&#xff0c;加快了行业的智能化发展&#xff0c;促使了行业需求在应用层上的落地。安防技术架构是物联网架构的一个子集&#xff0c;传统安防是一个相对保守的行业。现代安防和物联网在业务和技术上的融合发…

强连通分量(学习心得)

定义&#xff1a;有向图强连通分量&#xff1a;在有向图G中&#xff0c;如果两个顶点vi,vj间&#xff08;vi>vj&#xff09;有一条从vi到vj的有向路径&#xff0c;同时还有一条从vj到vi的有向路径&#xff0c;则称两个顶点强连通如果有向图G的每两个顶点都强连通&#xff0c…

java for的增强_Java基础之增强for循环

平时大家for循环应该用的不少&#xff0c;特别是增强for循环&#xff0c;简单快捷。但是在增强for中做删除操作&#xff0c;却会抛出java.util.ConcurrentModificationException&#xff0c;一起来看下。上面的代码&#xff0c;在for循环执行完if中的remove&#xff0c;遍历下一…

lintcode:递归打印数字

题目 用递归打印数字 用递归的方法找到从1到最大的N位整数。 样例 给出 N 1, 返回[1,2,3,4,5,6,7,8,9]. 给出 N 2, 返回[1,2,3,4,5,6,7,8,9,10,11,...,99]. 注意 用下面这种方式去递归其实很容易&#xff1a; recursion(i) {if i > largest number:returnresults.add(i)r…

做免费的EDM,EmailCar看中的是挖掘数据的价值

从2008年开始&#xff0c;做了9年企业级EDM&#xff08;电子邮件营销&#xff09;服务的陆霏近日宣布&#xff0c;他们的产品EmailCar从4.0版本开始永久免费为企业提供电子邮件基础投递业务。 我们电子邮箱经常收到的推广邮件就属于EDM&#xff0c;即Email Direct Marketing。这…

java 读取split_Java报错系列——split

在String中,split方法如下&#xff1a;可见&#xff0c;split的核心在于Pattern.compile(regex).split(this, limit);Java提供Pattern,Matcher用于支持正则&#xff0c;可以看一个例子&#xff1a;运行结果是&#xff1a;0,1||3,4|ab|7,8|cef|8,9||11,12|kk|13,14|a|需要注意的…

VS2012生成事件

Visual Studio 事件生成功能对我们开发综合项目的过程中尤为重要。 下面以VS2012为例&#xff1a; 选择工程-> 属性->编译->生成事件 包括两个生成事件&#xff1a;预先生成事件和后期生成事件 直接在相应的文本框里编写写脚本即可&#xff0c;如&#xff1a;编译完成…

H3C Navigate 2017 | 拉近世界的距离 新华三的泛联接版图

就今天而言&#xff0c;联接世界的网络外延已经无限扩大&#xff0c;联接的方式也越来越复杂。从互联网时代的PC互联&#xff0c;演进到移动互联网时代手机等移动终端的互联&#xff0c;而即将大规模爆发的物联网应用时代&#xff0c;所有的事物都可能被连入网络&#xff0c;一…

大数据时代的公共安全治理

未来&#xff0c;大数据将成为社会基础设施的一部分&#xff0c;跟公路、自来水、电一样&#xff0c;成为人们生活不可或缺的一部分。但大数据的作用并不仅仅局限于为普通消费者提供生活必须服务&#xff0c;它已经开始在信息产业、公共安全、交通运输、金融、水利等领域中发挥…

CCNA第二讲笔记

网络定义&#xff1a;一组由介质&#xff08;线缆&#xff09;互联的网络设备&#xff08;路由器、交换机&#xff09;和终端系统&#xff08;PC&#xff09;&#xff1b; 工作组&#xff1a;局域网范畴&#xff0c;范围最小的局域网&#xff0c;且不涉及网络设备。台式机需要有…