悲观锁 和 乐观锁

悲观锁

当我们要对数据库中的⼀条数据进⾏修改的时候,为了避免同时被其他⼈修改,最

好的办法就是直接对该数据进⾏加锁以防⽌并发。这种借助数据库锁机制在修改数

据之前锁定,再修改的⽅式被称为悲观并发控制(PCC)。

之所以叫做悲观锁,是因为抱有悲观的态度去修改数据的并发控制⽅式,认为数据

并发修改的概率⽐较⼤,所以需要在修改之前先加锁。

悲观并发控制实际上是 “先取锁,再访问” 的保守策略,为数据处理的安全提供了

保证。

在效率上,处理加锁的机制会让数据库产⽣额外的开销,还会有死锁的可能性。降

低并⾏性,⼀个事务如果锁定了某⾏数据,其他事务就必须等待该事务处理完才可

以处理那⾏数据。

悲观锁的实现⽅式:悲观锁的实现,依靠数据库提供的锁机制。

在数据库中,悲观锁的流程如下:

在对数据修改前,尝试增加排他锁。

加锁失败,意味着数据正在被修改,进⾏等待或者抛出异常。

加锁成功,对数据进⾏修改,提交事务,锁释放。

如果我们加锁成功,有其他线程对该数据进操作或者加排他锁的操作,只能

等待或者抛出异常。

乐观锁

乐观锁是相对悲观锁⽽⾔的,乐观锁假设数据⼀般情况下不会造成冲突,所以在数据进⾏提交更新的时候,才会正式对数据的冲突与否进⾏检测。

相对于悲观锁,在数据库进⾏处理的时候,乐观锁不会使⽤数据库提供的锁机制,

⼀般是增加 version 参数,记录数据版本

乐观并发控制相信事务之间的数据竞争概率⾮常⼩,因此尽可能直接操作,提交的

时候才去锁定,不会产⽣任何锁和死锁。

上⼿试⼀试

基于 MySQL InnoDB 引擎

使⽤悲观锁

begin;

select quantity from products where id = 1 for update;

update products set quanntity = 2 where id = 1;

commit;

以上,对 id 为 1 的产品进⾏修改,先通过 for update 的⽅式进⾏加锁,然后再修

改。典型的悲观锁策略。

如果修改库存的逻辑发⽣并发,同⼀时间只有⼀个线程可以开启事务并获得 id = 1

的锁,其他事务必须等本次提交之后才能执⾏,这样可以保证数据不被其他事务修

改。

使⽤排他锁会把数据锁住,不过需要注意⼀些基本的锁级别,MySQL InnoDB 默认⾏级锁。⾏级锁是基于索引的,如果⼀条 SQL 语句⽤不到索引是不会使⽤⾏级

锁,会使⽤表级锁把整张表锁住。

使⽤乐观锁

select quantity from products where id = 1

update products set quantity = 2 where id = 1 and quantity  = 3

先查询库存表当前库存数,然后更新的时候判断数据表对应数据的 quantity 与第

⼀次取出来的是否⼀致,⼀致则更新,否则认为是过期数据。

这样实现有⼀个问题,线程 1 从数据库取出 quantity 为 3,线程 2 也取出同⼀条

数据的 quantity,进⾏操作,变成了 2,然后⼜进⾏某些操作 变成了 3,此时线程

  1. 进⾏更新操作成功。但是这个过程有问题。

引⼊ version 参数,乐观锁每次在执⾏数据修改的操作,都会带上版本号,⼀旦版

本号和数据的版本号⼀致就可以执⾏修改操作并对 version 执⾏ +1 操作,否则就

执⾏失败。

这样实现也有⼀个问题,如果真的有⾼并发的时候,就只有⼀个线程可以修改成

功,就会存在⼤量的失败。

如果你的应⽤存在超⾼并发,这样解决也不好,因为会总让⽤户感知到失败。

尝试减⼩乐观锁⼒度,最⼤程度提⾼吞吐。

update products set quantity = quantity - 1 where id = 1

and quantity - 1 > 0

使⽤这条 SQL 语句,在执⾏过程中,会在⼀次原⼦操作中查询⼀遍 quantity 的

值,并且减去 1。

简述区别

  1. 乐观锁不是真的加锁,效率低,性能高,但是要控制好锁的⼒度。

  2. 悲观锁依赖数据库锁,效率高,性能低。

总结

⽆论是悲观锁还是乐观锁,都是⼈们定义出来的概念,可以认为是⼀种思想。

⼤家要记住锁机制⼀定要在事务中才能⽣效哦。

以上是我对乐观锁与悲观锁⼀点基础实践,希望能和⼤家再深⼊了解了解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值