悲观锁与乐观锁

点评实习三面的时候被问到这个问题,现在整理一下,自己也加深印象。

数据库方面

1.悲观锁

概念:悲观锁在操作数据库过程中,认为其他外部操作会改变改变数据,因此将数据锁定,直到其操作完成。

做法:使用数据库提供的锁机制。

实现:使用“select * from B where id = 100 for update”,这条语句锁定了B表中id=100的记录,在该事务提交之前,外界是无法修改或读取该数据的。

举例:mysql innodb

           set autocommit = 0;//设置事务不是自动提交

           begin;或 start transanction;//开始事务

           select * from B where id = 100 for update;

           update B set status =1 where id = 100;

          commit;//提交事务

注意点:比如上面这个事务,当有第二个事务select * from B where id = 100 for update时候,会等待第一个事务完成;

               但是,select 语句不会受影响,可以读数据。

缺点:加锁的机制会导致效率低,影响其他用户访问。

2.乐观锁

概念:一般认为数据不会发生冲突,只有在提交的时候才检查数据是否有冲突,如果有冲突,返回错误信息,用户自己选择如何处理

做法:数据版本记录机制;给表增加一个字段,版本号或者时间戳。

           版本号:读取数据时候,将版本号读出,数据每更新一次,version号+1,当提交更新的时候,检查版本号是否一致;一致的话,就进行更新;不一致的话,拒绝更新,用户重新操作;

          时间戳:读取数据的时候,将时间戳读出,数据每次更新,将当前时间存入,当提交更新的时候,检查时间戳是否与上一次读取的相同,一致则更新,不一致,拒绝更新,用户重新操作;

Hibernate中乐观锁 悲观锁

1. 悲观锁

String hqlStr ="from TUser as user where user.name=Max";  
Query query = session.createQuery(hqlStr);  
query.setLockMode("user",LockMode.UPGRADE); //加锁  
List userList = query.list();//执行查询,获取数据  

生成的sql语句:

select tuser0_.id as id, tuser0_.name as name, tuser0_.group_id as group_id, tuser0_.user_type as user_type, tuser0_.sex as sex from t_user tuser0_ where (tuser0_.name='Erica' ) for update

可以看到也是用select ... for update实现的

2.Hibernate的加锁机制

LockMode.NONE:无锁

LockMode.WRITE:在写操作自动获取写锁(update insert)

LockMode.READ:在读取记录时候自动获取

上述三种在Hibernate内部使用,比如为了保证update过程中对象不会被外界修改,在save方法中自动为目标对象加WRITE锁。

LockMode.upgrade:利用sql for update实现

LockMode. UPGRADE_NOWAIT :Oracle的特定实现,利用Oracle的for update nowait子句实现加锁。

3.乐观锁

实现一、 配置optimistic-lock属性:

<hibernate-mapping>  
     <class name="org.hibernate.sample.TUser" table="t_user" dynamic-update="true" dynamic-insert="true" optimistic-lock="version">  
           ……  
     </class>  
</hibernate-mapping> 

optimistic-lock属性有如下可选取值:
     Ø none:无乐观锁
     Ø version:通过版本机制实现乐观锁
     Ø dirty:通过检查发生变动过的属性实现乐观锁
     Ø all:通过检查所有属性实现乐观锁

实现二、添加一个Version属性描述符

<hibernate-mapping>  
     <class name="org.hibernate.sample.TUser" table="t_user"   dynamic-update="true" dynamic-insert="true" optimistic-lock="version">   
    <id name="id" column="id" type="java.lang.Integer">  
        <generator class="native"/>  
    </id>  
    <version column="version" name="version" type="java.lang.Integer"/>  
……  
     </class>  
</hibernate-mapping>  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值