乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段

无论是悲观锁还是乐观锁,都是人们定义出来的概念,可以认为是一种思想,悲观锁正是利用数据库本身提供的锁机制来实现的

详见:http://www.hollischuang.com/archives/934

简介

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block(阻止限制)直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry(再审),这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适

悲观锁介绍

悲观锁是一种并发控制的方法,可以阻止一个事务以影响其他用户的方式来修改数据,如果一个事务执行的操作在某行应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作

主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中。

悲观锁的实现,往往依靠数据库提供的锁机制 (也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)

悲观锁一般是用于并发不是很高,并且不允许脏读等情况。但是对数据库资源消耗较大

悲观锁实现方式

在对任意记录进行修改前,先尝试为该记录加上排他锁(排他锁又称写锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁,获准排他锁的事务既能读数据,又能修改数据)

如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。 具体响应方式由开发者根据实际需要决定

如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了

其间如果有其他对该记录做修改或加排他锁的操作,都会等待我们解锁或直接抛出异常

悲观锁优缺点

采用先取锁再访问的方式,为数据处理的安全提供了保证

会增加额外的开销,增加死锁的机会

在只读型事务处理中不会产生冲突,也没必要使用悲观锁

降低了并行性,一个事务锁住了某行数据,其他事务就必须等待该事物处理完才能处理

 

乐观锁介绍

是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据,在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚

乐观锁在实际应用相对较多,它可以提供更好的并发访问,并且数据库开销较少,但是有可能存在脏读的情况

乐观锁实现方式

一般的实现乐观锁的方式就是记录数据版本

当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新,否则认为是过期数据

实现数据版本有两种方式,第一种是使用版本号,第二种是使用时间戳