乐观离线锁(optimistic offline lock )
通过冲突监测和事务回滚来防止并发业务事务中的冲突。
一个业务事务的执行常常要跨越一系列的系统事务。而一旦超出单个系统事务的范围,就不能仅依靠数据库管理程序来确保业务事务将会使记录数据处以一致的状态中。当两个会话同时处理同样的记录时,很难保证数据的完整性,还可能丢失对数据的更新,当某个会话正在编辑数据时,其他的会话很可能读到不一致的数据。
用乐观离线锁可以解决这个问题,方法是要验证由一个会话提交的相关修改不会与其他会话中的修改发生冲突。
悲观离线锁假设会话冲突的可能性很大,从而对系统并发性进行限制,而乐观离线锁假设会话冲突的可能性很小,认为会话冲突不经常发生,这使多个用户同时对一份数据进行处理成为可能。
运行机制
乐观离线锁通过检查在会话读取一条记录后没有其他的会话修改改数据来包装数据的一致性。可以在任何时候获取一个乐观离线锁,但他只在获得该锁的系统事务过程中有效。因此,业务事务为了不破坏记录数据,必须对他在每一个系统事务中的变更集成员申请乐观离线锁,也就是说,只要系统事务中有对数据库的修改,就需要获取乐观离线锁。
最常见的实现方式是为每条记录关联一个版本号。
悲观离线锁(pessimistic offline lock)
每次只允许一个业务事务访问数据以防止并发业务事务中的冲突。
主要问题是:如果多个人在业务事务中访问同一数据,其中只有一个人能正常提交,其他人失败。
运行机制
通过三步来实现悲观离线锁:
1、决定需要使用哪种锁
2、构建一个锁管理对象,
3、定义业务事务使用锁的过程。
另外如果将悲观离线锁作为乐观离线锁的补充来使用,需要决定对那些记录类型加锁。
锁类型:
- 独占写锁(exclusive write lock ),在编辑会话时使用,对读不做要求
- 独占读锁(exclusive read lock ),仅仅为了读出数据才获取锁
- 读/写锁,提供互斥读锁的限制,又有互斥写锁的并发性。
- 读锁和写锁是互斥的,有读锁就不能加上写锁,有写锁就不能加上读锁
- 并发的读锁是允许的
定义业务事务使用锁管理对象的协议,协议说明对什么加锁,何时加锁,何时解锁,以及无法获取锁时的动作。
- 何时加锁,通常应该在读取数据前获取锁。
- 对什么加锁,一般对id或者主键加锁
- 释放锁,在业务事务结束时
粗粒度锁(Coarse-grained lock)
用一个锁锁住一组相关的对象
使用乐观离线锁为一组对象加一个版本号,悲观离线锁加一个统一的标记。
隐含锁(implicit lock)
允许框架或层超类型代码来获取离线锁。
必须加锁的任务不应该显式地由应用发开人员完成,而应该隐含的由应用完成。
乐观离线锁对每个表每行数据存储版本,在sql中统一判断。
本章主要讲解离线锁,当系统中有多个用户对同一数据进行操作时,必须保证修改的完整性和有效性。大多数情况下使用隐含的乐观离线锁。