欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL乐观锁是真正意义上的乐观锁?

程序员文章站 2022-06-04 14:21:30
...

在创作该文当天下午,看见某篇秒杀技术博客的文章说道利用mysql乐观锁提高并发(原文如下)

悲观锁虽然可以解决超卖问题,但是加锁的时间可能会很长,
会长时间的限制其他用户的访问,导致很多请求等待锁,
卡死在这里,如果这种请求很多就会耗尽连接,系统出现异常。
乐观锁默认不加锁,更失败就直接返回抢购失败,可以承受较高并发

突然发下自己对mysql乐观锁概念很是模糊,隐约知道有这个概念,便去网上搜索学习,然而在学习过程基本看到的都是:

乐观锁:
	新增字段version或者类似字段
	更新语句:update table1 set a=1, version = version + 1 where id = 2 and version = version  //  1
悲观锁
	更新语句:update table1 set a=1, version = version + 1 where id = 2  // 2

在看到这种解释和乐观锁实现方式后,认知观崩塌了。原因有2:

1. 都是MySQL数据库,使用的都是innodb引擎,都是update语句使用排他锁(for update),凭啥多了and version = version就叫乐观锁?
2. 难道上面两条语句的效果不是一样?当语句1执行时开启事务,在事务提交之前其它事务只能阻塞,事务提交后其他事务拿到最新view重新加锁,此时的version = version有起到作用?

于是乎,我便思索再三,自己给了份解释给自己!

首先,这种解释下mysql的乐观锁本质还是悲观锁,因为update语句mysql默认都是排他锁,典型的悲观锁。

其次,这种解释下mysql的乐观锁只能说是一种思想或者境界,反正挺玄乎的一个东西,并不是大家传统观念中的乐观锁cas这种。

最后,这种解释下mysql的乐观锁的update语句应该是update table1 set a=1, version = version + 1 where id = 2 and version = #{version} ,某种意义上的确是可以提高并发能力。比如,MySQL并发量较大,假设5000个连接需要去执行这条语句,就像小蝌蚪奔向终点形成受精软一样,一定会有一个幸运儿(连接)首先开启事务,执行update,其他4999个连接都阻塞等待幸运儿提交事务,这个时候就不会满足where id = 2 and version = #{version}条件而执行失败。否则的话剩余的4999个连接会重新竞争资源加锁,直到服务被打死,被老板开除,世界末日

ps: 上述栗子并不是很恰当,所以不要质疑谁会开启5000个mysql连接,为什么会世界末日。