`

Hibernate 的 LockMode 分析总结

阅读更多

悲观锁

在应用程序中显示地为数据资源加锁 . 悲观锁假定当前事务操纵数据资源时 , 肯定还会有其它事务同时访问该数据资源 , 为了避免当前事务的操作受到干扰 , 先锁定资源 . 尽管悲观锁能防止丢失更新和不可重复读这类并发问题 , 但会影响并发性能 .

 

乐观锁

假定当前事务操纵数据资源时 , 不会有其它事务同时访问该数据资源 , 因此完全依靠数据库的隔离级别来自动管理锁的工作 . 应用程序采用版本控制手段来避免可能出现的并发问题 .

 

LockMode 类表示的几种锁定模式

锁定模式

描述

LockMode.NONE

如果缓存中存在对象 , 直接返回该对象的引用 , 否则通过 select 语句到数据库中加载该对象 , 默认值 .

LockMode.READ

不管缓存中是否存在对象 , 总是通过 select 语句到数据库中加载该对象 , 如果映射文件中设置了版本元素 , 就执行版本检查 , 比较缓存中的对象是否和数据库中对象版本一致

LockMode.UPGRADE

不管缓存中是否存在对象 , 总是通过 select 语句到数据库中加载该对象 , 如果映射文件中设置了版本元素 , 就执行版本检查 , 比较缓存中的对象是否和数据库中对象的版本一致 , 如果数据库系统支持悲观锁 ( Oracle/MySQL), 就执行 select...for update 语句 , 如果不支持 ( Sybase), 执行普通 select 语句

LockMode.UPGRADE_NOWAIT

LockMode.UPGRADE 具有同样功能 , 此外 , 对于 Oracle 等支持 update nowait 的数据库 , 执行 select...for update nowait 语句 ,nowait 表明如果执行该 select 语句的事务不能立即获得悲观锁 , 那么不会等待其它事务释放锁 , 而是立刻抛出锁定异常

LockMode.WRITE

保存对象时会自动使用这种锁定模式 , 仅供 Hibernate 内部使用 , 应用程序中不应该使用它

LockMode.FORCE

强制更新数据库中对象的版本属性 , 从而表明当前事务已经更新了这个对象

 

 

多个事务并发运行时的并发问题

第一类丢失更新 : 撤销一个事务时 , 把其它事务已提交的更新数据覆盖 .

第二类丢失更新 : 不可重复读中的特例 , 一个事务覆盖另一事务已提交的更新数据 .

脏读 : 一个事务读到另一事务未提交的更新数据 .

幻读 : 一个事务读到另一事务已提交的新插入的数据 .

不可重复读 : 一个事务读到另一个事物已提交的更新数据 .

 

锁的类型和兼容性

共享锁

l   加锁条件 : 当一个事务执行 select 语句时 , 数据库系统会为这个事务分配一把共享锁 , 锁定被查询的数据 .

l   解锁条件 : 数据被读取后 , 数据库系统立即解除共享锁 .

l   与其它锁的兼容性 : 如果数据资源上放置了共享锁 , 还能再放置共享锁和更新锁 .

l   并发性能 : 良好的并发性能 . 当多个事务读相同数据时 , 每个事务都会获得一把共享锁 , 可以同时读锁定的数据 .

独占锁

l   加锁条件 : 当一个事务执行 insert,update,delete , 数据库系统会自动对 SQL 语句操纵的数据资源使用独占锁 . 如果该数据资源已经有其它锁存在时 , 无法对其再放置独占锁 .

l   解锁条件 : 独占锁一直到事务结束后才能被解除 .

l   与其它锁的兼容性 : 独占锁不能和其他锁兼容 , 如果数据资源已经加上了独占锁 就不能再放置其它锁 , 同样 , 如果已经有了其它锁 , 就不能放置独占锁 .

l   并发性能 : 并发性能较差 , 只允许有一个事务访问锁定的数据 , 如果其他事务也需要访问该数据 , 就必须等待 , 直到前一个事务结束 , 解除了独占锁 , 其它事务才能访问该数据 .

更新锁

l   加锁条件 : 当一个事务进行 update 操作时 , 数据库系统会先为事务分配一把更新锁 .

l   解锁条件 : 当读取数据完毕 , 执行更新操作时 , 会把更新锁升级为独占锁 .

l   与其它锁的兼容性 : 更新锁与共享锁兼容 , 即一个资源可以同时放置更新锁和共享锁 , 但是最多只能放置一把更新锁 , 这样 , 当多个事务更新相同的数据时 , 只有一个事务能获得更新锁 , 然后再把更新锁升级为独占锁 , 其它事务必须等到前一个事务结束后 , 才能获得更新锁 , 避免了死锁 .

l   并发性能 : 允许多个事务同时读锁定资源 , 但不允许其它事务修改它 .

 

各种隔离级别所能避免的并发问题

隔离级别

是否出现第一类丢失更新

是否出现第二类丢失更新

是否出现脏读

是否出现幻读

是否出现不可重复读

Serializable 串行化

RepeatableRead 可重复读

ReadCommited 读已提交数据

ReadUncommited 读未提交数据

 

0
0
分享到:
评论

相关推荐

    Hibernate悲观锁和乐观锁实例详解

    主要介绍了Hibernate悲观锁和乐观锁实例详解,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下

    hibernate3.2+cglib2.2架包

    内含hibernate3.2与修复java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter.(Z)V 的错误的cglib2.2

    南大通用GBase8s数据库锁监控及调整.docx

    通过监控数据库实例的锁使用情况,活跃锁的个数、死锁等信息,调整锁个数...1) onstat -k 监控当前活跃锁的个数,参照此设置LOCKS、DEF_TABLE_LOCKMODE参数,避免锁粒度太大、锁个数太多,浪费内存资源,从而影响性能。

    事务队列等待(TxEnqueue)深入分析——记录锁

    通过v$lock很容易鉴定出来:可以看到,LockMode为6.等待队列分析当发现系统中由于此类锁导致的等待而致使会话hung住时,可以通过以下过程来找到导致阻塞的会话、语句和对象。续上,在Session2中执行

    数据库锁表问题解决方法

    当某个数据库用户在数据库中插入、更新、删除一个表的数据,或者增加一个表的主键时或者表的索引时,常常会出现ora-00054:resource busy and acquire with nowait specified这样的错误。 主要是因为有事务正在执行...

    jdbc基础和参考

    3.hibernate的配置文件(hibernate.cfg.xml)得存在 4.POJO.hbm.xml文件存在 5.hibernate的jar包以及数据库的驱动包存在 Hibernate的编程: 1.构建Configuration对象读取配置文件 2.读取映射文件 3.构建SessionFactory...

    Android实现九宫格手势解锁

    本文为大家分享了Android九宫格手势解锁的具体代码,供... LockMode lockMode = (LockMode) getIntent().getSerializableExtra(Config.INTENT_SECONDACTIVITY_KEY); //是否显示手势的方向箭头 lv_lock.setShow(false)

    Python Sqlalchemy如何实现select for update

    sqlalchemy 对于行级锁有两种实现方式,with_lockmode(self, mode): 和 with_for_update(self, read=False, nowait=False, of=None),前者在sqlalchemy 0.9.0 被废弃,用后者代替。所以我们使用with_for_update ! 看...

Global site tag (gtag.js) - Google Analytics