摘自:http://www.cnblogs.com/otomedaybreak/archive/2012/01/27/2330008.html#C5
五、使用悲观锁解决事务并发问题
悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
一个典型的依赖数据库的悲观锁调用: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,让该记录所有的字段都为版本控制信息。
相关推荐
在处理并发问题时,Hibernate提供了悲观锁和乐观锁两种机制。 悲观锁假设并发环境中的冲突是常态,因此在读取数据时就立即锁定,直到事务结束才释放。在Hibernate中,可以通过设置`@LockModeType.PESSIMISTIC_READ`...
在实际应用中,选择使用乐观锁还是悲观锁,需要根据具体的业务场景和并发需求来定。如果业务操作大部分时间不会出现并发冲突,乐观锁是一种较好的选择;如果操作过程中并发冲突频繁,那么悲观锁可能更为适合。但无论...
而乐观锁适用于并发较低,对数据一致性要求高的情况,它减少了锁的使用,提升了性能,但无法避免脏读和不可重复读的问题。 在进行Hibernate的测试时,可以创建一个名为`hibernate_test`的项目,编写对应的实体类、...
- **优势**:乐观锁避免了长时间锁定数据的问题,提高了并发处理能力,降低了数据库锁定的开销。 - **局限**:如果多个事务同时尝试更新同一行数据,可能导致多次重试,降低效率。 **总结** 悲观锁和乐观锁各有优...
总的来说,Hibernate的悲观锁和乐观锁是处理并发问题的重要工具,开发者需要根据实际情况权衡性能和数据一致性,合理选择并使用合适的锁策略。在实际项目中,还可以结合使用其他的并发控制手段,如事务隔离级别、...
Hibernate 锁机制_悲观锁和乐观锁 Hibernate 锁机制是指在数据库访问中,为了维护数据的一致性和正确性,所采取的一些机制来防止数据的并发访问和修改。 Hibernate 中有两种锁机制:悲观锁和乐观锁。 一、悲观锁...
悲观锁和乐观锁是两种常见的并发控制策略,用于在多任务环境下确保数据一致性。它们各自有不同的工作原理和适用场景。 悲观锁(Pessimistic Lock)正如其名,它假设并发环境中会发生频繁的冲突,因此在读取数据时就...
主要分为两种类型:乐观锁(Optimistic Locking)和悲观锁(Pessimistic Locking)。 **悲观锁(Pessimistic Locking)** 悲观锁假设数据在任何时候都可能发生并发冲突,因此在数据读取时就对其进行锁定,确保在...
总结来说,Hibernate的悲观锁和乐观锁是两种不同的并发控制策略,悲观锁倾向于预防并发冲突,适合并发较低但需要保证数据一致性的情景;而乐观锁则在并发较高的情况下更优,通过版本控制减少锁定,但在冲突处理上...
**Hibernate**作为一种流行的Java持久层框架,提供了多种机制来处理并发控制问题,其中最常用的就是**乐观锁**和**悲观锁**。本文将详细介绍这两种锁的原理、应用场景以及如何在Hibernate中实现。 #### 二、悲观锁...
乐观锁和悲观锁是数据库事务控制...了解和掌握乐观锁与悲观锁的原理和应用场景,对于提升面试者的数据库管理技能和解决并发问题的能力至关重要。在面试中,深入探讨这些话题将有助于展示自己的专业水平和问题解决能力。
本文主要讨论的是Hibernate框架中两种锁机制的使用:乐观锁和悲观锁。 首先,让我们深入理解悲观锁(Pessimistic Locking)。悲观锁正如其名字所示,假设并发环境中数据会被频繁修改,所以在整个数据处理过程中,它...
本文将深入探讨如何使用Django框架中的乐观锁和悲观锁机制来解决订单并发问题,确保数据的一致性和准确性。 首先,我们需要了解什么是事务。在数据库管理中,事务是一组操作,这些操作要么全部成功,要么全部失败。...
本文将探讨 Mybatis-Plus 中乐观锁 @version 注解的问题和解决方案。 什么是乐观锁? 乐观锁是一种并发控制机制,它假设多个事务可以同时访问同一个资源,而不会互相干扰。只有当事务提交时,系统才会检查是否有...
在IT行业中,尤其是在Java开发领域,面试者常常会被问及并发控制策略,其中乐观锁和悲观锁是两个非常重要的概念。这两个术语涉及到数据库事务处理、多线程编程以及并发性能优化等多个方面。本文将深入探讨这两种锁...
在MySQL数据库中,悲观锁(Pessimistic Lock)和乐观锁(Optimistic Lock)是两种常见的并发控制机制,它们用于解决多用户环境下同一资源的并发访问问题。这两种锁各有特点,适用于不同的业务场景。 首先,悲观锁...