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