面试中被问到了,查找资料整理下。
悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
以常用的mysql InnoDB存储引擎为例:加入商品表items表中有一个字段status,status=1表示该商品未被下单,status=2表示该商品已经被下单,那么我们对每个商品下单前必须确保此商品的status=1。假设有一件商品,其id为10000;如果不使用锁,那么操作方法如下:
//查出商品状态
select status from items where id=10000;
//根据商品信息生成订单
insert into orders(id,item_id) values(null,10000);
//修改商品状态为2
update Items set status=2 where id=10000;
上述场景在高并发环境下可能出现问题:
前面已经提到只有商品的status=1是才能对它进行下单操作,上面第一步操作中,查询出来的商品status为1。但是当我们执行第三步update操作的时候,有可能出现其他人先一步对商品下单把Item的status修改为2了,但是我们并不知道数据已经被修改了,这样就可能造成同一个商品被下单2次,使得数据不一致。所以说这种方式是不安全的。
使用悲观锁来实现:在上面的场景中,商品信息从查询出来到修改,中间有一个处理订单的过程,使用悲观锁的原理就是,当我们在查询出items信息后就把当前的数据锁定,直到我们修改完毕后再解锁。那么在这个过程中,因为items被锁定了,就不会出现有第三者来对其进行修改了。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
以mysql InnoDB存储引擎为例,还是拿之前的例子商品表items表中有一个字段status,status=1表示该商品未被下单,status=2表示该商品已经被下单,那么我们对每个商品下单前必须确保此商品的status=1。假设有一件商品,其id为10000;
下单操作包括3步骤:
//查询出商品信息
select (status,version) from items where id=#{id}
//根据商品信息生成订单
//修改商品status为2
update items set status=2,version=version+1 where id=#{id} and version=#{version};
为了使用乐观锁,我们需要首先修改items表,增加一个version字段,数据默认version可设为1;
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
771

被折叠的 条评论
为什么被折叠?



