悲观锁
在应用程序中显示地为数据资源加锁.悲观锁假定当前事务操纵数据资源时,肯定还会有其它事务同时访问该数据资源,为了避免当前事务的操作受到干扰,先锁定资源.尽管悲观锁能防止丢失更新和不可重复读这类并发问题,但会影响并发性能.
乐观锁
假定当前事务操纵数据资源时,不会有其它事务同时访问该数据资源,因此完全依靠数据库的隔离级别来自动管理锁的工作.应用程序采用版本控制手段来避免可能出现的并发问题.
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
l
l
l
独占锁
l
l
l
l
更新锁
l
l
l
l
各种隔离级别所能避免的并发问题
隔离级别 | 是否出现第一类丢失更新 | 是否出现第二类丢失更新 | 是否出现脏读 | 是否出现幻读 | 是否出现不可重复读 |
Serializable串行化 | 否 | 否 | 否 | 否 | 否 |
RepeatableRead可重复读 | 否 | 否 | 是 | 否 | 否 |
ReadCommited读已提交数据 | 否 | 否 | 是 | 是 | 是 |
ReadUncommited读未提交数据 | 否 | 是 | 是 | 是 |
是
|