前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mysql之MVCC(五)

mysql之MVCC(五)

原创
作者头像
翰墨飘香
修改2023-10-31 20:19:48
3420
修改2023-10-31 20:19:48
举报
文章被收录于专栏:翰墨飘香

一、MVCC概念

全称Multi-Version Concurrency Control,即多版本并发控制。它是一种并发控制的方法,它可以维护一个数据的多个版本,用更好的方式去处理读写冲突,做到即使有读写冲突也能不加锁。

一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存

https://dev.mysql.com/doc/refman/8.0/en/innodb-multi-versioning.html

https://www.modb.pro/db/572479

https://ost.51cto.com/posts/11846

https://blog.csdn.net/turodog/article/details/115616860

https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/MySQL%E5%AE%9E%E6%88%9845%E8%AE%B2/08%20%20%E4%BA%8B%E5%8A%A1%E5%88%B0%E5%BA%95%E6%98%AF%E9%9A%94%E7%A6%BB%E7%9A%84%E8%BF%98%E6%98%AF%E4%B8%8D%E9%9A%94%E7%A6%BB%E7%9A%84%EF%BC%9F.md

二、当前读 快照读

在学习 MVCC 多版本并发控制之前,我们必须先了解一下,什么是 MySQL InnoDB 下的当前读和快照读?

  • 当前读 像 select lock in share mode (共享锁), select for update; update; insert; delete (排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁 更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)
  • 快照读 像不加锁的 select 操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即 MVCC ,可以认为 MVCC 是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

说白了 MVCC 就是为了实现读-写冲突不加锁,而这个读指的就是快照读, 而非当前读,当前读实际上是一种加锁的操作,是悲观锁的实现

二、MVCC实现原理

MySQL中MVCC的具体实现,还需要依赖于表中的三个隐藏字段、Undo Log日志以及ReadView

2.1 三个隐藏字段

InnoDB引擎还自动为我们添加了三个隐藏字段,见下表:

字段

含义

DB_TRX_ID

最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID

DB_ROLL_PTR

回滚指针,指向这条记录的上一个版本(地址),用于配合Undo Log,指向上一个版本

DB_ROW_ID

隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段

2.2 Undo log存储的MVCC版本链

当有多个并发事务操作一行数据时,对这行数据的修改会产生多个版本,多个版本通过上述的一个隐藏字段DB_ROLL_PTR

回滚指针指向Undo Log数据地址形成一个链表,即MVCC版本链

2.3 ReadView视图

注意 在 MySQL 里,有两个“视图”的概念:

  • 一个是 view。它是一个用查询语句定义的虚拟表,在调用的时候执行查询语句并生成结果。创建视图的语法是 create view … ,而它的查询方法与表一样。
  • 另一个是 InnoDB 在实现 MVCC 时用到的一致性读视图,即 consistent read view,用于支持 RC(Read Committed,读提交)和 RR(Repeatable Read,可重复读)隔离级别的实现。 ReadView读视图是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。

上面讲过Undo Log和MVCC版本链,一条数据经过多次修改会产生多个版本,而快照读是根据不同时机创建的快照获取数据的,那么快照读SQL在执行时该读取那个版本的数据就是靠ReadViw读视图来决定的。

ReadView读视图中包含了四个核心字段,也是读取数据的判断依据:

字段

含义

m_ids

当前活跃的事务ID集合

min_trx_id

最小活跃事务ID

max_trx_id

预分配事务ID,当前最大事务ID+1(因为事务ID是自增的)

creator_trx_id

ReadView创建者的事务ID

ReadView一共有四种匹配规则:

条件

能否访问

说明

trx_id == creatro_trx_id

可以访问该版本 成立,

说明数据是当前这个事务更改的。

trx_id < min_trx_id

可以访问该版本

成立,说明数据已经提交了。

trx_id > max_trx_id

不可以访问该版本

成立,说明该事务是在ReadView生成后才开启的。

min_trx_id <= trx_id <= max_trx_id

如果trx_id不在m_ids中,那么可以访问该版本

成立,说明数据已经提交。

数组里面事务 ID 的最小值记为低水位,当前系统里面已经创建过的事务 ID 的最大值加 1 记为高水位。

这个视图数组和高水位,就组成了当前事务的一致性视图(read-view)。

而数据版本的可见性规则,就是基于数据的 row trx_id 和这个一致性视图的对比结果得到的。

这个视图数组把所有的 row trx_id 分成了几种不同的情况。

这样,对于当前事务的启动瞬间来说,一个数据版本的 row trx_id,有以下几种可能:

如果落在绿色部分,表示这个版本是已提交的事务或者是当前事务自己生成的,这个数据是可见的;

如果落在红色部分,表示这个版本是由将来启动的事务生成的,是肯定不可见的;

如果落在黄色部分,那就包括两种情况 a. 若 row trx_id 在数组中,表示这个版本是由还没提交的事务生成的,不可见; b. 若 row trx_id 不在数组中,表示这个版本是已经提交了的事务生成的,可见。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、MVCC概念
  • 二、当前读 快照读
  • 二、MVCC实现原理
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档