事务高并发事务处理,怎么样不会数据丢失

385被浏览16391分享邀请回答cs.umb.edu/~poneil/iso.pdf[2]: update: 感谢 @interma 指正,之前看 8.0 的文档太老了,postgres 9.6 的文档中显示内部有 RC, RR, Serializable 三种隔离级别,而非 8.0 文档中的只有 RC 和 Serializable 两种:8.0In PostgreSQL, you can request any of the four standard transaction isolation levels. But internally, there are only two distinct isolation levels, which correspond to the levels Read Committed and Serializable. 9.6 In PostgreSQL, you can request any of the four standard transaction isolation levels, but internally only three distinct isolation levels are implemented6419 条评论分享收藏感谢收起1321 条评论分享收藏感谢收起求教讲解下高并发场景下的数据一致性问题?- 百度派
{{ mainData.uname }}
:{{ mainData.content }}
{{ prevData.uname }}
:{{ prevData.content }}
{{ mainData.uname }}
:{{ mainData.content }}
0 || contentType !== 1" class="separate-line">
:{{ item.content }}
3">等{{ uList.length }}人邀请你回答
求教讲解下高并发场景下的数据一致性问题?
如题,数据一致性问题如何保证
问题说明(可选):
扫一扫分享到微信
{{ log.sign }}
可能对你的问题感兴趣
暂无相关用户
,才能邀请用户
,才能邀请用户
你已邀请15人,不可再邀请
,逛吃逛吃逛吃逛吃逛吃逛吃
问题背景:在学习事务的时候,我们都知道,对于交易行为,我们必须保证整个过程的原子性,即转出金额和转入金额必须同时成功或者同时失败。实际项目中,我们可以利用数据库的事务来保证,但当交易的数量过...
问题背景:在学习事务的时候,我们都知道,对于交易行为,我们必须保证整个过程的原子性,即转出金额和转入金额必须同时成功或者同时失败。实际项目中,我们可以利用数据库的事务来保证,但当交易的数量过多,像支付宝和微信,每秒钟都需要处理上百万条的交易,如何去确保数据的一致性并保证请求的并发数?各大土豪银联商务的系统,都是基于IOE,对于一般的企业,是承担不起这高昂的维护费用的。就连干爹阿里也在14年开始了去IOE行动。对于支付业务,参考了别人,加上自己的业务特性,探究了如何通过开源、低廉的服务去实现同样强一致性的需求,做一个记录~技术选型:Nginx、PHP、Redis,MCQ,MySQL,MC基本概念:二阶段提交绝大多数的事务中的失败,都是因为资源的占用冲突导致的,我们只要避免这种冲突,就能保障事务的一定完成。Prepare:对每一个自事务进行资源锁定,事务进入Ready状态Commit:执行所有子事务操作,事务进入Success状态Rollback:如果中间有失败,回退到初始状态,事务进入Cancel状态数据恢复如果出现服务中断的情况,通过检查所有状态不是Cancel和Success状态的事务,对其进行Rollback操作,将所有中间状态的子事务恢复为Cansel状态。确保不会因为意外,导致亏损、坏账。具体实例:提高性能,总的来说分为分库、缓存、异步三种方式来实现。分库:由于用户量的庞大,我们将账户表Hash到64张表上,这样如果继续提高TPS,就可以简单的通过横向扩展DB实例来提升了。==注意:==分布式事务降低了单个事务的执行效率,提升的是并行数扩展DB实例需要在不同的物理机上扩展,仅仅扩展端口号是解决不了DB的并发瓶颈支付交易:图1每一个方块内的行为是依赖MySQL提供的事务来保证原子性图2只是展示了简单的转账行为,涉及到两个账户,这么看来似乎还没有直接执行操作来的轻松。其实不然,如果是更复杂的类似打赏,红包的支付行为,涉及到十几、二十的账户,这种分布式事务的优势就体现出来了。首先从账户中预扣费,可以避免提交时账户无钱可扣的情况出现。0,1,2分别代表ready,success,cancel状态,提交时把ready的全部执行,回滚时把所有ready状态回滚到cancel。Tid是标识子事务隶属于同一个大事务,可以通过基于Redis的发号器来实现。Tid还有另一个用途,用它来防止多次提交,同一个Tid我们只处理一次。(这里确保只处理一次,我们利用Redis的SETNX来实现分布式的锁,网上例子很多,等做完也会做个记录)异步:涉及到钱此类比较敏感、用户特别关心的我们使用分库可以缓解性能瓶颈,对于支付完之后的业务操作行为,如支付订单的生成,收款成功消息的发送,业务方的服务等,这些事务性并不是强要求,我们可以通过消息队列来进行异步的执行。这里需要关心的问题是:确保队列消息的不丢失,参考Http协议的三次握手协议,需要通过一个协调者去校验每次获取的消息。缓存:支付业务暂不考虑缓存,对于要求的强一致性,缓存这里并不可取。
扫一扫分享到微信
求教讲解下高并发场景下的数据一致性问题?
,才能进行回答
一个问题只能回答一次,请&nbsp点击此处&nbsp查看你的答案
1人关注了此问题相关文章推荐
我们要明白秒杀系统的难点:高并发
快速响应。
大数据量的处理,难点就是在事务处理和复杂计算上。为了提高系统的响应速度,就要采用集群+多线程的处理方式。而数据库显然就成了整个系统的...
今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过;但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识。今天就我的一些理解,整理一下...
一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构、性能的要求都很简单,随着互联网业务的不断丰富,网站...
多个事务并发运行时的并发问题
第一类丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖
脏读:一个事务读到另一个事务未提交的数据
虚读:一个事务读到另一个事务已提交的新插入的数据
一、并发的场景
1、用户访问并发(一般发生在用户数量多,访问同一个功能频繁)
2、程序处理并发(一般发生在多线程访问)
3、数据库读写并发(一般发生事物之间导致脏读...
1 什么是并发问题。
多个进程或线程同时(或着说在同一段时间内)访问同一资源会产生并发问题。
银行两操作员同时操作同一账户就是典型的例子。比如A、B操作员同时读取一余额为1000元的账...
大并发大数据量请求一般会分为几种情况:
1.大量的用户同时对系统的不同功能页面进行查找,更新操作
2.大量的用户同时对系统的同一个页面,同一个表的大数据量进行查询操作
3.大量的用户同时对系统的...
并发中的问题通常为了获得更好的运行性能,各种数据库都允许多个事务同时运行,这就是事务并发。当并发的事务访问或修改数据库中相同的数据时,通常需要采取必要的隔离机制,反之会出现各种并发问题。这些并发问题可...
对于同时运行的多个事务,当这些 访问数据库中相同的数据时,如果没有必要的隔离机制,就会导致各种并发问题,这些问题可以归纳为以下几类:
1、第一类丢失更新:撤销一个事务时,把其他事务已提交更新的数据覆...
事务处理是在数据处理时经常遇到的问题,经常用到的方法有以下3种总结整理如下:方法1:直接写入到sql 中在存储过程中使用 BEGIN TRANS, COMMIT TRANS, ROLLBACK TRA...
他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)博客分类:
Hibernate事务与并发问题处理(乐观锁与悲观锁)
一、数据库事务的定义
  数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。
  1. 原子性(atomic),事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行
  2. 一致性(consistent),事务在完成时,必须使所有的数据都保持一致状态。
  3. 隔离性(insulation),由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。
  4. 持久性(Duration),事务完成之后,它对于系统的影响是永久性的。
二、数据库事务并发可能带来的问题
  如果没有锁定且多个用户同时访问一个数据库,则当他们的事务同时使用相同的数据时可能会发生问题。由于并发操作带来的数据不一致性包括:丢失数据修改、读”脏”数据(脏读)、不可重复读、产生幽灵数据:
假设数据库中有如下一张表:
  1. 第一类丢失更新(lost update): 在完全未隔离事务的情况下,两个事物更新同一条数据资源,某一事物异常终止,回滚造成第一个完成的更新也同时丢失。
  在T1时刻开启了事务1,T2时刻开启了事务2,在T3时刻事务1从数据库中取出了id="194b8f10001"的数据,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="194b8f10001"的数据,在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="194b8f10001"的数据,此时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&
&!-- version标签用于指定表示版本号的字段信息 --&
&version name="version" column="version" type="integer"&&/version&
&property name="name" column="name" type="string"&&/property&
&/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&
&!-- timestamp标签用于指定表示版本号的字段信息 --&
&timestamp name="updateDate" column="updateDate"&&/timestamp&
&property name="name" column="name" type="string"&&/property&
&/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&
&property name="name" column="name" type="string"&&/property&
&/hibernate-mapping&
将该属性的值设置为all,让该记录所有的字段都为版本控制信息。
浏览: 1524 次
来自: 北京
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'数据库事务中的基本概念
数据库事务是指,由一个或多个SQL语句组成的工作单元,这个工作单元中的SQL语句相互依赖,如果有一个SQL语句失败,那么整个操作都要撤销。在并发环境中,当多个事务同时访问同一资源时,可能会造成并发问题,此时可以使用数据库系统的事务隔离级别来避免各类并发问题。此外,在应用程序中还可以使用悲观锁和乐观锁来解决丢失更新的并发问题。
数据库事务必须具备ACID的特征(Atomic原子性,Consistency一致性,Isolation隔离性,Durability持久性)
&&& 原子性,指整个数据库事务是不可分割的单元。只有所有的语句执行成功,才算成功。
&&& 一致性,指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
&&&& 隔离性,指在并发环境中,当不同的事务同时操作相同的数据时,每个事务都有各自的完整数据空间。
&&&& 持久性,指的是只要事务成功结束,对数据库做的更新要永久保存下来.
Transaction和Session的关系,应该注意以下几点
&&&&& Transaction的rollback()和Session的close()方法都会抛出HibernateException
&&&& 不论事务是否成功,最后都应该关闭Session。
&&&&& 即使事务中只包含只读操作,也应该在事务成功执行之后提交事务,并且在事务执行失败时撤销事务,因为在提交或撤销事务时,数据库系统会释放占用的资源。
多个事务同时运行时的并发问题
&&&& 第一类丢失更新,撤销一个事务时,把其他事务已提交的更新数据覆盖了。
&&&& 脏读,一个事务读到另一个事务未提交的更新数据。
&&&& 虚读,一个事务读到另一个事务已提交的新插入的数据。
&&&& 不可重复读,一个事务读到另一个事务已提交的更新数据。
&&&&& 第二类更新,一个事务覆盖另一事务已提交的更新数据。
数据库系统锁的基本原理
按照锁定的资源的粒度,锁可以分为以下类型
&& 数据库级锁: 锁定整个数据库
&& 表级锁: 锁定一张表
&& 区域级锁: 锁定数据库的特定区域
&& 页面级锁: 锁定数据库的特定页面
&& 见面级锁: 锁定数据库的特定页面
&& 键值级锁: 锁定数据库表中带有索引的一行数据。
&& 行级锁: 锁定数据库表中的但行数据(即一条记录)
按照封锁的程度,锁可以分为: 共享锁,独占锁,更新锁
共享锁, 共享锁用于读数据操作,它是非独占的,允许其他事务同时读取其锁定的资源,但不允许其他事务更新数据。共享锁的特征:
加锁条件:当一个事务执行Select操作时,数据库系统就会为其分配一把共享锁,来锁定查询数据。
&&&& 解锁条件:在默认情况下,数据读取完毕,共享锁就解除了。
&&&& 与其他锁的兼容性:如果数据资源上放置了共享锁,还能再放置共享锁和更新锁。
&&&& 并发性能:具有良好的并发性能,当多个事务读相同的数据时,每个事务都会获得共享锁,因此可以同时读锁定的数据。
独占锁,也叫排它锁,适用于修改数据的场合。它锁定的资源,其他事务不能读取也不能更新。独占锁具有以下特征:
&&& 加锁的条件:当一个事务执行insert、update、或delete语句时,数据库就会为SQL所操作的数据使用独占锁。如果数据上有其他锁,那么就能放置独占锁.
&&& 解锁条件:到事务结束时才能被解除
与其他锁的兼容性:独占锁不能和其他锁兼容。通用如果资源上有其他锁,那么也不能放置独占锁。
&&& 并发性能:性能较差,只允许有一个事务访问锁定的数据,如果其他事务也需要访问该数据,就必须等待,直到前一个事务结束,解除了独占锁,其他事务才有机会访问资源。
更新锁,在更新操作的初始化阶段用来锁定可能要被修改的资源,这可以避免使用共享锁造成死锁的现象。更新具有以下特征:
&&& 加锁的条件:当一个事务执行update语句时,数据库系统会先为事务分配一把更新锁。
&&& 解锁条件:读取数据完毕,执行更新操作时,会把更新锁升级为独占锁。
&&&& 与其他锁的兼容性:更新锁与共享锁是兼容的。也就是说,一个资源可以同时放置更新锁和共享锁,但是最多只能放置一把更新锁。
&&& 并发性能:允许多个事务同时访问资源。但不允许修改。
死锁及其防止方法
&&&& 合理安排表的访问顺序
&&&& 使用短事务。将大事务分割为多个小事务执行。应该在处理事务之前就准备好用户必须提供的数据。
&&&& 如果对数据的一致性要求不高,可以允许脏度。
&&&& 如果可能,错开多个事务访问相同数据资源的时间,以防止锁冲突。
&&&& 使用尽可能低的事务级别。
数据库的隔离级别
&&&& 尽管数据库系统允许用户在事务中显示的为数据资源加锁,但是首先应该考虑让数据库系统自动管理锁,它会分析事务中的SQL语句,然后自动为SQL语句所操作的数据资源加上合适的锁,而且在锁的数目太多时,数据库系统会自动的进行锁升级,以提供系统性能。
数据库系统提供了四种事务隔离级别供用户选择:
Serializable,串行化。
&&&&& 一个事务在执行过程中完全看不到事务对数据库所做的更新。当两个事务同时操作数据库中的数据时,如果第一个事务已经在访问该数据,那么第二个事务只能停下来等待。
Repeatable Read:可重复读
&&&&& 一个事务在执行过程中可以看到其他事务已经提交的新插入的数据。但是不能看到其他事务对已有数据做的跟新。
Read Commited:读已提交数据
&&&&& 一个事务在执行过程中可以看到其他事务已经提交的新插入的数据。可以看到其他对已有数据进行的更新。
Read UnCommited:读取未提交
&&&& 一个事务可以看到,其他事务没有提交新插入的数据。而且更新操作的记录也能看到。
//: 在hibernate.cfg.xml中配置
hibernate.connection.isolation=2
在应用程序中才用悲观锁和乐观锁
悲观锁与乐观锁的概念
悲观锁,在应用程序中显示的为数据资源加锁。可以防止丢失更新和不可重复读问题。但是会影响性能。
乐观锁,假设当前的事务操作的数据,不会有其他事务同时访问该数据资源,完全依靠数据库系统自动管理锁。因此可能会出现并发问题。
利用数据库系统的独占锁来实现悲观锁
悲观锁的两种实现方式
应用中显示的指定采用数据库系统的独占锁来锁定数据资源。
在数据库表中增加一个表明记录状态的LOCK字段,当它取值为Y时,表示该i记录已被某个事务锁定。如果为N,表示该条数据为空闲状态。
在Hibernate中,当通过Session的get()和load()方式来加载一个对象时,可以采用以下方式使用悲观锁:
Customer cus = (Customer)session.get(Customer.class, "c001", LockMode.UPGRADE); //: final org.hibernate.LockMode
LockMode类表示的几种锁定模式
锁定模式 描述
LockMode.NONE 如果在Hibernate缓存中存在Customer对象,就直接返回该引用。否则通过select加载。默认值
LockMode.READ 不管缓存中是否有,都使用select加载数据。如果映射文件设置了版本元素,就执行版本检查,比较缓存中的与取到的是否版本一致。
LockMode.UPGRADE 不管缓存中是否有,都使用select加载数据。就执行版本检查,比较缓存中的与取到的是否版本一致。如果数据库系统支持悲观锁,那么执行select…for update, 否则执行简单的select
LockMode.UPGRADE_NOWAIT 会执行LockMode.UPGRADE和它一样的功能。若果执行的select不能立即获得悲观锁,那么就会抛出异常
LockMode.WRITE 当Hibernate保存或更新对象时,会自动使用这种锁定模式。这种锁定模式只在Hibernate内部使用,所以在应用中不应该使用它
利用Hibernate的版本控制来实现乐观锁
create table Accounts (
primary key,
varchar(15),
numeric(10,2),
LAST_UPDATED_TIME timestamp,
在hbm中配置版本控制
//: 在元素必须跟在&id&元素的后面
&version name = "version" column = "VERSION" /&
//: 使用该元素也可以实现版本控制
&timestamp name=”lastUpdateTime” column=” LAST_UPDATED_TIME” /&
对游离对象进行版本检查
Session session1 = ....;
trans1 = session1.beginTransaction();
Account a = (Account)session1.get(Account.class, new Long(1));
mit();
session1.close();
a.setBalance(a.getBalance()-100);
Session session2 = ...;
trans2 = session2.beginTransaction();
session2.lock(a, LockMode.READ);
mit();
session2.close();
lock() 方法和update()方法之间的区别
lock()方法在LockMode.READ模式下,立即进行版本控制。而update()方法不会立即执行版本检查,只有当Session清理缓存时,真正执行update时才进行版本检查
lock()在默认的LockMode中不会执行update语句。而update()会计划执行一个update语句,如果数据库中没对应的记录那么会抛出异常。
实现乐观锁的其他方式
&class optimistic-lock="all" dynamic-update="true"&
//: optimistic-lock=all/dirty 时必须设置dynamic-update为true
描述: doc文档可能看的更加清楚。
下载次数: 210
论坛回复 /
(0 / 3528)
浏览: 167844 次
来自: 上海
&developer&
您好!麻烦可以把SplitPageUI、Page、Consta ...
不错,不错,借鉴一下
不好意思,全部的源码没空整理出来!这里给出的代码片段,也是为了 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 mysql 事务 并发 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信