乐观锁:乐观锁在操作数据时,非常乐观,以为别人不会同时在修改数据。因此乐观锁不会上锁,只是在执行更新的时候判定一下,在此期间是否有人修改了数据。 乐观锁的实现:
就是给表多加一列 version 版本号,每次更新数据前,先查出来确认下是不是刚刚的版本号,没有改动再去执行更新,并升级 version(version=version+1)。
比如,我们更新前,先查一下数据,查出来的版本号是 version=1。
select order_id,version from order where order_id=‘666’;
然后使用 version=1 和 订单ID 一起作为条件,再去更新:
update order set version = version +1,status=‘P’ where order_id=‘666’ and version =1
末了,更新成功才可以处理业务逻辑,如果更新失败,默以为重复请求,直接返回。 流程图如下:
为什么版本号发起自增呢?
因为乐观锁存在 ABA 的题目,如果 version 版本一直是自增的就不会出现 ABA 的情况。
3.3 数据库层面,悲观锁(select for update)【不保举】
悲观锁:通俗点讲就是很悲观,每次去操作数据时,都觉得别人中途会修改,所以每次在拿数据的时候都会上锁。官方点讲就是,共享资源每次只给一个线程使用,其他线程阻塞,用完后再把资源转让给其它资源。 悲观锁的实现:
在订单业务场景中,假设先查询出订单,如果查到的是处理中状态,就处理完业务,然后再更新订单状态为完成。如果查到订单,并且不是处理中的状态,则直接返回。
可以使用数据库悲观锁(select … for update)解决这个题目:
begin; # 1.开始事务
select * from order where order_id=‘666’ for update # 查询订单,判定状态,锁住这条记录
if(status !=处理中){
//非处理中状态,直接返回;
return ;
}
处理业务逻辑
update order set status=‘完成’ where order_id=‘666’ # 更新完成
commit; # 5.提交事务
留意: