mysql
一、 乐观锁
和 悲观锁
乐观锁
和 悲观锁
是实现并发操作的两种不同的 加锁思想
,其中:
-
乐观锁
假设:操作能成功,不需要事先加锁,只要在真正提交时验证本次修改是否可以提交
,如果不可以提交,则重新尝试更新。 -
悲观锁
假设:操作不能成功,需要事先对要更新的数据加锁,操作成功后再释放锁,以便其他线程能获得锁。
二、 MVCC
实现思路
MVVC
,全名 Multi-Version Concurrency Control
,即:多版本并发控制
,是 MySQL 的 InnoDB 存储引擎下,repeatable-read
和 read-committed
隔离级别时事务的 乐观锁
的实现方案。大概的实现思路是:
- 在 InnoDB 的表中增加两个隐藏字段:
创建版本号
和删除版本号
。 - 在开启一个事务时,生成一个事务的版本号。
- 被操作的数据,会临时生成一条新的记录,这条
临时记录
对其他事务时不可见的(事务的隔离性原则)。 - 如果事务执行成功,会将
更新后的数据
和事务的版本号
更新到真实的记录上,同时删除临时记录。 - 因此,在
MVCC
中,其实是不存在锁
的,既避免了争锁等问题,又保证了并发操作。
三、 MVCC
下的 CURD
1. insert
将当前的事务版本号作为数据的创建版本号。
2. delete
将当前的事务版本号作为数据的删除版本号。
3. update
- 基于要删除的行,复制出一个临时行。
- 将当前事务的版本号设置为要删除数据的删除版本号。
- 将当前事务的版本号设置为临时行的创建版本号。
- 事务提交时,用临时行替换要删除的行。
4. select
同时满足一下两个条件的数据,会作为查询结果返回:
- 条件一:数据的创建版本号小于等于事务版本号。即:在事务开始前,数据是存在的。
- 条件二:数据的删除版本号未定义或者大于事务版本号。即:在事务开始前,数据还没被删除。
四、MVCC
优缺点
1. 优点:
- 因为
MVCC
中并没有使用锁,从而避免了锁
的资源浪费和争锁
、死锁
等问题。 - 使用两个隐藏的版本号和事务版本号巧妙的解决了
不可重复读
的问题。 -
读
不加锁,速度快。 -
读
和写
不冲突。
2. 缺点:
- 存储了更多数据(两个隐藏的版本号字段)
- 增加了很多检查工作和处理完后的善后工作。
- 只能在
repeatable-read
和read-committed
隔离级别下工作。 -
read-uncommitted
隔离级别下MVCC
每次都获取到最新的事务版本号。 -
serializable
隔离级别时,读操作锁定了返回的每一行。