Python 乐观锁与悲观锁
参考:https://xie.infoq.cn/article/2085a95ad6b486d3905adc7d6
乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题
什么是乐观锁 ?
乐观锁在操作数据时采用乐观的态度,认为不会出现多个操作数据的事件。因此乐观锁不糊上锁,只是在进行更新操作的时候
判断该期间是否同时存在修改了数据的情况:若在修改时数据已被修改则放弃操作,否则继续执行操作。
乐观锁的实现
- CAS 机制。2.版本号机制。这里将采用 python + orm 的实现方式
CSA (Compare and Swap)
CSA 的操作主要包括了 3 个操作数:
- 需要读写的内存位置(V)
- 进行比较的预期值(A)
- 拟写入的新值(B)
具体的操作逻辑为:若内存位置的值等于预期的 A 值,则将该位置更新为新值 B, 否则不进行任何操作。
直到重试次数消耗完毕。CSA 实现
乐观锁(Optimistic Lock),适用于多读
1 | from django.shortcuts import render |
什么是悲观锁 ?
悲观锁在操作数据的时候,比较悲观,认为别人会同时修改数据。
因此操作数据时会直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据
简单实现
例如,有用户 A 和用户 B,在同一家店铺去购买同一个商品,但是商品的可购买数量只有一个
若,用户 A 和用户 B 同时下单,就会报错。
悲观锁的实现,往往依靠数据库提供的锁机制,在数据库中,我们如何用悲观锁去结局这个事情呢?
- 用户 A 在执行购买商品的时候,先尝试对该商品加上悲观锁。
- 若加锁失败,说明商品正在被其他事务进行修改,当前查询需要等待或者抛出异常,具体返回的方式需要开发者根据具体情况去定义
- 加锁成功:对商品进行修改
- 在此期间如果有其他用户对数据做修改或加锁的操作,都会等待我们解锁后或直接抛出异常
实际操作
那么如何加上悲观锁呢,1. 首先关闭 MySQL 数据库的自动提交属性。因为 MySQL 默认使用 autocommit 模式(默认提交)
1 | set autocommit = 0; |
悲观锁加锁 sql 语句:
1 | select num form t_goods where id = 2 for update |
此时,其他事务都不能获取到此行的数据去进行操作。