一、死锁

1.死锁是什么?

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去,进入无限等待的状态。

2.示例

6.1.png
死锁示例
事务2等待事务1释放 字段0 = 1 的行锁,事务1等待事务2 字段0=2 的行锁,进入死锁状态。

3.解决策略

A.等待直到超时;可通过innodb_lock_wait_timeout参数来设置等待时间,默认值为 50s。
6.2.png
B.回滚其中一个事务,让其他事务继续进行;此设置需通过下面这个参数开启,“ON”即开启。
6.3.png
C.预防策略:控制并发度

二、悲观锁和乐观锁

1.含义

乐观锁和悲观锁都是并发场景下控制数据处理过程的主要方法。

悲观锁(Pessimistic Locking):每次去拿数据的时候都认为别人会修改数据,所以每次拿数据的时候,都会使数据处于锁定状态。

乐观锁(Optimistic Lock):每次去拿数据的时候都认为别人不会修改数据,所以不会上锁,仅会在数据进行提交更新的时候,才会去检查别人有没有对数据进行修改(检查是否冲突)。

2.实现思路简述

以一个比较经典的实现场景为例,“购买物品,生成订单并修改库存数量”,大致会进行以下三个步骤的操作:

A.查询物品信息;

B.根据物品信息生成订单数据;

C.更新库存数量。

悲观锁:

悲观锁在进行A操作“查询物品信息”时,就会给对应的数据上锁;

例如:

select * from goods where id = 1 for update;

直接以排他锁的形式锁定了对应的数据。

(这里有一个注意点:"select ... for update" 会锁住sql语句执行过程中所有扫描过的数据行,所以,你应该确保这条sql语句使用了索引)

乐观锁:

使用“数据版本”的机制,为数据库增加一个“数据版本”的字段(每次有更新操作时,都会 版本号+1);

当我们读取数据时,同时读取版本号;如果要更新数据,则需要同时更新版本号(version+1);当我们更新数据的时候,要将读取数据时的版本号和现在数据库中的版本号进行对比,如果相同,则更新,反正,则更新失败,由用户自行决定后面的逻辑处理。



萌新初入江湖,有理解不足之处,望指正!

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

一个喜欢拔刀的萌新Coder