# 概述
并发访问控制作为数据库领域非常重要的一个问题,目前已经有比较成熟的解决方案,这里介绍三种。
* 悲观并发控制
* 乐观并发控制
* 多版本并发控制
悲观并发控制最常见,也就是我们经常说的悲观锁。
乐观并发控制表示乐观锁,乐观锁不是真正的锁,而表示了一种并发控制策略。
多版本并发控制(MVCC),不同于乐观锁和悲观锁的互斥关系,它能够和乐观锁悲观锁任意一种结合使用,显著提升数据库的读性能。
# 悲观并发控制 - 锁
确保资源在同一时刻只能被一个事务独占。通过悲观锁来实现。
**当一个事务需要操作资源时需要先获得该资源的锁**,保证了在一个事务归还锁之前,其他事务无法获取该资源的锁。
## 锁类型
* 共享锁(读锁)
* 互斥锁(写锁)
为了让数据库的并发能力最大化,数据库设计了两种锁,分别是共享锁和互斥锁。当一个事务获得行记录的共享锁时,只能对行进行读操作。当获取记录行的互斥锁时,能够对行进行读,写操作。
共享锁,互斥锁除了能够限制事务对资源的读写,相互之间还有限制关系。多个事务可以获得同一资源的共享锁,而只能有一个事务获得某一资源的互斥锁。
当事务无法获得资源的锁时,就会陷入阻塞状态。直到其他事务释放锁。
## 加锁方式
通过图1可以发现,**两阶段锁协议**的加锁和解锁处于两个阶段,在加锁阶段,锁的数量逐个增加。**一次性锁协议**在开始阶段需要获得全部数量的锁
* 一次性锁协议
* 事务开始时,一次性申请所有的锁,无法获取部分数据的锁时,无法开启事务
* 提交事务时释放所有锁
* 避免了死锁
* 并发性不高,事务中的记录被加锁,从事务开始到提交
* 两阶段锁协议
* 整个事务分为两个阶段,第一阶段是从开启事务开始,到提交事务/回滚结束,只能加锁,不能解锁。第二阶段只能解锁。
* 出现了死锁
* 并发性相比一次性锁协议有明显提升
* 提升性能考虑,在事务中操作数据的顺序,应当按照热点升序。参考图2的库存表记录
![](https://box.kancloud.cn/fe1eaf3f0412d8aaec6ef957fa31f207_707x362.png)
:-: 图1
![](https://box.kancloud.cn/cdf0a028895f88fa475e67bf513a7c78_726x362.png)
图2
## 死锁
悲观锁的在解决事务并发的同时,引入了死锁的问题。
解决死锁的两种策略,
1. 预防死锁的发生
2. 发生死锁之后的处理
### 预防死锁
1. 事务开始时将涉及到的所有资源原子性锁定。
2. 抢占加事务回滚。
每个事务被开启时,获得数据库分配的一个时间戳。事务之间触发死锁时,数据库通过对比事务的时间戳来执行不同的方案。
* wait-die。如图3。1 等待另一个事务释放锁。2 保持当前时间戳当前事务回滚。
* round-wait。如图4。1 另一个事务立马回滚。2 当前事务等待。
![](https://box.kancloud.cn/a2d55843113b3d6b7e51e627fcafed05_848x783.png)
图3
![](https://box.kancloud.cn/7d8a895086bedacdfb85159b61b23310_840x665.png)
图4
### 死锁检测和修复
当预防死锁的机制无法生效时,数据库需要有一个检测事务是否进入死锁状态,并解决死锁问题的机制。
## 锁的粒度
根据锁定的数据范围将锁粒度分为数据库锁,表锁,行锁。
* 父节点被加锁时,所有子节点会被加上隐式锁。避免子节点被加锁
* 子节点被加锁时,对应的父节点会被加上意向锁。避免父节点被加锁。意向锁之前完全不会互斥
# 乐观并发控制
乐观并发控制也成为乐观锁,但跟悲观锁不一样,乐观锁并不是真正的锁,只是一种并发控制策略。
## 实现策略
1. 在数据中新增字段version,表示当前的数据版本,每次数据更新,version值会+1
2. 事务a读取该数据,通过字段version获得数据版本为1
3. 事务a写入之前校验数据版本是否为1,1的情况下更新数据,同时更新字段version+1;否则终止事务a,数据更新失败。
# MVCC
多版本并发控制,InnoDB支持多种隔离级别,其中的重复读 repeatable read 是通过MVCC实现的。
“版本“指的是事务ID(translate ID),数据库维护累计的事务数量,每开启一个事务,数量累加。InnoDB下数据的记录格式,除了字段本身之外,额外维护了两个字段
* DATA_TRX_ID:最新一次更新该数据行的事务ID
* DATA_ROLL_PTR:指向undo Log中旧版本数据的指针
![](https://box.kancloud.cn/fd1d075eae496bd82fe88aa12edaa98c_821x304.png)
## 参考资料
[浅谈数据库并发控制 - 锁和 MVCC](https://draveness.me/database-concurrency-control)