乐观锁和悲观锁的简单实现

数据库表:seckill

在这里插入图片描述
在这里插入图片描述

乐观锁:

乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

即很乐观,查询数据的时候总觉得不会有人更改数据,等到更新的时候再判断这个数据有没有被人更改,有人更改了则本次更新失败。
优点:乐观锁机制避免了长事务中的数据库加锁开销,大大提升了大并发量下的系统整体性能表现。
缺点:由于乐观锁机制是在我们的系统中实现,来自外部系统的number更新操作不受我们系统的控制,因此可能会造成脏数据被更新到数据库中。
样例:

UPDATE seckill  SET number=number-1,version=version+1 WHERE seckill_id=1000 AND version = 0

在这里插入图片描述

悲观锁:

根据命名即对数据进行操作更新时,对操作持悲观保守的态度,认为产生数据冲突的可能性很大,需要先对请求的数据加锁再进行相关的操作。实现方式:通过数据库锁机制实现,即对查询语句添加for update关键字。

即很悲观,每次拿数据的时候都觉得数据会被人更改,所以拿数据的时候就把这条记录锁掉,这样别人就没法改这条数据了,一直到你的锁释放。
优点:每一次行数据的访问都是独占的,只有当正在访问该行数据的请求事务提交以后,其他请求才能依次访问该数据,否则将阻塞等待锁的获取。悲观锁可以严格保证数据访问的安全。
缺点:每次请求都会额外产生加锁的开销且未获取到锁的请求将会阻塞等待锁的获取,在高并发环境下,容易造成大量请求阻塞,影响系统可用性。另外,悲观锁使用不当还可能产生死锁的情况。
样例:

SELECT number FROM seckill WHERE seckill_id=1001 FOR UPDATE;
UPDATE seckill  SET number=number-1 WHERE seckill_id=1001;

在这里插入图片描述
并发量较小、又需要独占读取结果并依赖读取的结果进行判断的业务场景比较适合使用悲观锁。

发布了50 篇原创文章 · 获赞 85 · 访问量 161万+

猜你喜欢

转载自blog.csdn.net/qq_24347541/article/details/94388727