介绍了解乐观锁和悲观锁

简述乐观锁和悲观锁

乐观锁和悲观锁都是一种思想,并不是真实存在于数据库中的一种机制。

悲观锁

当认为数据被并发修改的几率比较大,需要在修改之前借助于数据库锁机制,先对数据进行加锁的思想被称为悲观锁,又称PCC(Pessimistic Concurrency Control)。在效率方面,处理锁的操作会产生了额外的开销,而且增加了死锁的机会。当一个线程在处理某行数据的时候,其它线程只能等待。

悲观锁的实现方式

悲观锁的实现是依赖于数据库提供的锁机制,流程如下:
1.修改记录前,对记录加上排他锁(exclusive locking)
2.如果加锁失败,说明这条数据正在被修改,那么当前查询要等待或者抛出异常,这由开发者决定
3.如果加锁成功,可以对这条数据修改了,事务完成解锁
4.加锁修改期间,其他事务也想对这条记录进行操作时,都要等待或者直接抛出异常

在使用mysql Innodb引擎实现悲观锁时,必须关闭mysql的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。set autocommit=0;

举例说明下单扣减库存如何使用悲观锁实现

//0.开始事务
begin; 
//1.查询出商品库存信息
select quantity from items where id=1 for update;
//2.修改商品库存为2
update items set quantity=2 where id = 1;
//3.提交事务
commit;

使用select…for update会把数据锁住。MySQL InnoDB默认行级锁,行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用表级锁把整张表锁住,这点需要注意

乐观锁

乐观锁思想认为,数据一般是不会造成冲突的。只有在提交数据的时候,才会对数据的冲突进行检测。当发现冲突的时候,返回错误的信息,让用户决定如何去做。
乐观锁不会使用数据库提供的锁机制,一般的实现方式就是记录数据版本。

乐观锁的实现方式

乐观锁的实现不需要借助于数据库锁机制,只要就是两个步骤:冲突检测和数据更新,其中一种典型的是实现方法就是CAS(Compare and Swap)

CAS实现乐观锁

CAS是一种乐观锁实现方式,顾名思义就是先比较后更新。在对一个数据进行更新前,先持有对这个数据原有值的备份。比如,要将a=2更新为a=3,在进行更新前会比较此刻a是否为2.如果是2,才会进行更新操作。当多个线程尝试使用CAS同时更新一个变量时,只有一个线程能够成功,其余都是失败。失败的线程不会被挂起,而是被告知这次竞争失败,并且可以再次尝试。
比如前面的扣减库存问题,乐观锁方式实现如下:

//查询出商品库存信息,quantity = 3
select quantity from items where id=1
//修改商品库存为2
update items set quantity=2 where id=1 and quantity = 3;

在更新之前,先查询库存表中当前库存数,然后在做update时,以库存数作为一个修改条件。当进行提交更新的时候,判断数据库的当前库存数与第一次取出来的库存数进行比对,相等则更新,否则认为是过期数据。
但是这种更新存在一个比较严重的问题,即ABA问题。

ABA问题

A线程去除库存数3,B线程取出库存数3,B线程先将库存数变为2,又将库存数变为3,A线程在进行更新操作时发现库存是仍然是3,然后操作成功。尽管A线程操作是成功的,但是不能代表这个过程就是没问题的

解决ABA问题的一个方法是通过一个顺序递增的version字段:

//查询出商品信息,version = 1
select version from items where id=1
//修改商品库存为2
update items set quantity=2,version = 2 where id=1 and version = 1;

在每次执行数据的修改操作时,都会带上一个版本号,一旦版本号和数据版本号一致就可以执行修改操作并对版本号执行+1操作,否则执行失败。因为每次修改操作都会将版本号增加,所以不会出现ABA问题。还可以使用时间戳,因为时间戳天然具有顺序递增性。

##乐观锁和悲观锁对比
乐观锁并不是真正的加锁,优点是效率高,缺点是更新失败的概率比较高;悲观锁依赖于数据库锁机制,更新失败的概率比较低,但是效率也低。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值