前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL的多版本并发控制(MVCC).

MySQL的多版本并发控制(MVCC).

作者头像
JMCui
发布2020-12-29 11:24:14
7800
发布2020-12-29 11:24:14
举报
文章被收录于专栏:JMCuiJMCui

一、快照读与当前读

快照读(SnapShot Read) 是一种一致性不加锁的读,是 InnoDB 并发如此之高的核心原因之一。

在 READ COMMITTED 事务隔离级别下,一致性不加锁的读是指,总是读取被锁定行的最新一份快照数据,因此其它事务修改了该行数据,该事务也能读取到,这也贴合了 RC 隔离级别下存在幻读的问题;

在 REPEATABLE READ 事务隔离级别下,一致性不加锁的读是指,事务读取到的数据,要么是事务开始前就已经存在的数据,要么是事务自身插入或者修改过的数据。(下面将以此隔离级别说明);

不加锁的简单的 SELECT 都属于快照读,例如:

代码语言:javascript
复制
SELECT * FROM t WHERE id=1;

与快照读相对应的则是当前读(Current Read),当前读就是读取最新数据,而不是历史版本的数据。加锁的 SELECT 就属于当前读,例如:

代码语言:javascript
复制
SELECT * FROM t WHERE id=1 LOCK IN SHARE MODE;
SELECT * FROM t WHERE id=1 FOR UPDATE;

SELECT...FOR UPDATE 对读取的行记录加一个 X 锁,其它事务不能对已锁定的行加上任何锁。

SELECT...LOCK IN SHARE MODE 对读取的行记录加一个 S 锁,其它事务可以向被锁定的行加 S 锁,但是如果加 X 锁,则会被阻塞。

二、基于快照读的多版本并发控制

多版本并发控制技术的英文全称是:Multiversion Concurrency Control,简称 MVCC,是通过保存数据的历史版本,通过对数据行的多个版本管理来实现数据库的并发控制。这样我们就可以通过比较版本号决定数据是否显示出来,读取数据的时候不需要加锁也可以保证事务的隔离效果(可以理解成乐观锁)。

多版本并发控制(MVCC)只在可重复读(REPEATABLE READ)和提交读(READ COMMITTED)两个隔离级别下工作,其他两个隔离级别都和 MVCC 不兼容,因为未提交读(READ UNCOMMITTED),总是读取最新的数据行,而不是符合当前事务版本的数据行;而可串行化(SERIALIZABLE) 则会对所有读取的行都加锁。

MySQL 的大多数事务型存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制(MVCC)。不仅是 MySQL,包括 Oracle、PostgreSQL 等其他数据库系统也都实现了 MVCC,但各自的实现机制不尽相同,因为 MVCC 没有一个统一的实现标准,典型的有乐观(optimistic)并发控制和悲观(pessimistic)并发控制。

三、多版本并发控制解决了哪些问题?

1. 读写之间阻塞的问题

通过 MVCC 可以让读写互相不阻塞,即读不阻塞写,写不阻塞读,这样就可以提升事务并发处理能力。

提高并发的演进思路:

  • 普通锁,只能串行执行;
  • 读写锁,可以实现读读并发;
  • 数据多版本并发控制,可以实现读写并发。

2. 降低了死锁的概率

因为 InnoDB 的 MVCC 采用了乐观锁的方式,读取数据时并不需要加锁,对于写操作,也只锁定必要的行。

3. 解决一致性读的问题

一致性读也被称为快照读,当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果。

四、InnoDB 的 MVCC 是如何工作的?

1. InnoDB 是如何存储记录的多个版本的?

事务版本号: 每开启一个事务,我们都会从数据库中获得一个事务 ID(也就是事务版本号),这个事务 ID 是自增长的,通过 ID 大小,我们就可以判断事务的时间顺序。

行记录的隐藏列: InnoDB 的叶子段存储了数据页,数据页中保存了行记录,而在行记录中有一些重要的隐藏字段:

  • DB_ROW_ID:6-byte,隐藏的行 ID,用来生成默认聚簇索引。如果我们创建数据表的时候没有指定聚簇索引,这时 InnoDB 就会用这个隐藏 ID 来创建聚集索引。采用聚簇索引的方式可以提升数据的查找效率。
  • DB_TRX_ID:6-byte,操作这个数据的事务 ID,也就是最后一个对该数据进行插入或更新的事务 ID。(InnoDB 的插入、更新、删除都会更新该事务 ID,同时删除会将一个特殊位标记为已删除)
  • DB_ROLL_PTR:7-byte,回滚指针,也就是指向这个记录的 Undo Log 信息。

Undo Log: InnoDB 将行记录快照保存在了 Undo Log 里,我们可以在回滚段中找到它们,如下图所示,回滚指针将数据行的所有快照记录都通过链表的结构串联了起来,每个快照的记录都保存了当时的 db_trx_id,也是那个时间点操作这个数据的事务 ID。这样如果我们想要找历史快照,就可以通过遍历回滚指针的方式进行查找。

参考链接:MySQL的多版本并发控制(MVCC)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-12-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、快照读与当前读
  • 二、基于快照读的多版本并发控制
  • 三、多版本并发控制解决了哪些问题?
    • 1. 读写之间阻塞的问题
      • 2. 降低了死锁的概率
        • 3. 解决一致性读的问题
        • 四、InnoDB 的 MVCC 是如何工作的?
          • 1. InnoDB 是如何存储记录的多个版本的?
          相关产品与服务
          云数据库 SQL Server
          腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档