MySQL之乐观锁·MVCC

mysql

一、 乐观锁悲观锁

乐观锁悲观锁 是实现并发操作的两种不同的 加锁思想,其中:

  • 乐观锁 假设:操作能成功,不需要事先加锁,只要在真正提交时验证 本次修改是否可以提交,如果不可以提交,则重新尝试更新。
  • 悲观锁 假设:操作不能成功,需要事先对要更新的数据加锁,操作成功后再释放锁,以便其他线程能获得锁。

二、 MVCC 实现思路

MVVC,全名 Multi-Version Concurrency Control,即:多版本并发控制,是 MySQL 的 InnoDB 存储引擎下,repeatable-readread-committed 隔离级别时事务的 乐观锁 的实现方案。大概的实现思路是:

  • 在 InnoDB 的表中增加两个隐藏字段:创建版本号删除版本号
  • 在开启一个事务时,生成一个事务的版本号。
  • 被操作的数据,会临时生成一条新的记录,这条 临时记录 对其他事务时不可见的(事务的隔离性原则)。
  • 如果事务执行成功,会将 更新后的数据事务的版本号 更新到真实的记录上,同时删除临时记录。
  • 因此,在 MVCC 中,其实是不存在 的,既避免了争锁等问题,又保证了并发操作。

三、 MVCC 下的 CURD

1. insert

将当前的事务版本号作为数据的创建版本号。

2. delete

将当前的事务版本号作为数据的删除版本号。

3. update
  • 基于要删除的行,复制出一个临时行。
  • 将当前事务的版本号设置为要删除数据的删除版本号。
  • 将当前事务的版本号设置为临时行的创建版本号。
  • 事务提交时,用临时行替换要删除的行。
4. select

同时满足一下两个条件的数据,会作为查询结果返回:

  • 条件一:数据的创建版本号小于等于事务版本号。即:在事务开始前,数据是存在的。
  • 条件二:数据的删除版本号未定义或者大于事务版本号。即:在事务开始前,数据还没被删除。

四、MVCC 优缺点

1. 优点:
  • 因为 MVCC 中并没有使用锁,从而避免了 的资源浪费和 争锁死锁 等问题。
  • 使用两个隐藏的版本号和事务版本号巧妙的解决了 不可重复读 的问题。
  • 不加锁,速度快。
  • 不冲突。
2. 缺点:
  • 存储了更多数据(两个隐藏的版本号字段)
  • 增加了很多检查工作和处理完后的善后工作。
  • 只能在 repeatable-readread-committed 隔离级别下工作。
  • read-uncommitted 隔离级别下 MVCC 每次都获取到最新的事务版本号。
  • serializable 隔离级别时,读操作锁定了返回的每一行。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。