【MySQL技术之旅】(1)MVCC运行原理机制

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 【MySQL技术之旅】(1)MVCC运行原理机制

前提概要


大家都知道数据库本身操作的是底层的文件系统的文件以及内存的数据结构,当存在多个请求并发执行修改或者读取相关的数据信息的时候,就会存在数据一致性的问题和数据安全的问题。MySQL数据库引擎主要依靠MVCC解决大多数的数据访问一致性的问题。




MVCC概念介绍


MVCC即多版本并发控制主要是为了解决数据库中并发事务读写的一致性问题,是乐观锁的一种实现方式,可以做到读不加锁,读写不冲突,解决读-写冲突的无锁并发控制。那么多个事务并发执行的时候事务的隔离到底是怎么实现的呢?


MySQL默认的RR隔离级别是怎样避免不可重复读的问题呢?好好来分析一下。





三种数据库并发场景


  • 读-读:不存在任何问题,也不需要并发控制


  • 读-写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读


  • 写-写:有线程安全问题,可能会存在更新丢失问题,脏写的操作处理。


MVCC 只在 Read Commited 和 Repeatable Read 两种隔离级别下工作。
复制代码




快照读与当前读的解释


快照读:


   简单的select操作,不需要加锁,基于MVCC和undo log来实现的,读取的是记录的可见版本(有可能是历史版本)。


当前读:


   特殊的读操作,需要加锁,是悲观锁的实现,读取的是记录的最新版本,并且当前读返回的记录,都会加锁,保证其他事务不会再并发修改这条记录。


insert/update/delete
select ...for update
select ... lock in share mode
复制代码




MVCC的底层实现


数据库中的实现,就是为了解决读写冲突,它的实现原理主要是依赖记录中的 3个隐式字段,undo log ,delete_sit,Read View 来实现的。


InnoDB MVCC的实现基于undo log,通过回滚指针来构建需要的版本记录。通过ReadView来判断哪些版本的数据可见。同时Purge线程是通过ReadView来清理旧版本数据。(insert的方式不需要,因为没有前一个版本且只对本线程考虑可见性问题)




三个隐式字段


DB_TRX_ID

6byte,最近修改(修改/插入)事务ID:记录创建这条记录/最后一次修改该记录的事务ID


DB_ROLL_PTR

7byte,回滚指针,用于配合undo log,指向这条记录的上一个版本


DB_ROW_ID

6byte,隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引



注意:

实际上每条记录的头信息(record header)里都有一个专门的bit(deleted flag)来表示当前记录是否已经被删除。

image.png


undo log


基本概念


undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。



作用


用于事务的回滚


  • undo日志用于存放数据修改被修改前的值,如果这个修改出现异常,可以使用undo日志来实现回滚操作,保证事务的一致性。


  • undo日志,只将数据库逻辑地恢复到原来的样子,回滚时候,它实际上是做的相反的工作


用于MVCC


undo log的类型主要分为:insert undo log和update undo log


insert undo log(插入undolog文件)

insert undo log是指在insert操作中产生的undo log,因为insert操作的记录,只对事务本身可见,对其他事务不可见。故该undo log可以在事务提交后直接删除,不需要进行purge操作。



update undo log(更新undolog文件)

update undo log记录的是对delete和update操作产生的undo log,该undo log可能需要提供MVCC机制,因此不能再事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行最后的删除。



具体工作原理需要分以下情况讨论




更新主键


聚簇索引和二级索引都无法进行in place update,都会产生两个版本


update分两步执行,先删除该行,再插入一行目标行

image.png


更新非主键


聚簇索引可以in place update,二级索引产生两个版本,聚簇索引记录undo log,二级索引不记录undo log,更新二级索引,同时需要判断是否修改索引页面的MAX_TRX_ID


image.png



清理undo log


清除page里面带有Delete_Bit标识的数据行。在InnoDB中,事务中的Delete操作实际上并不是真正的删除掉数据行,而是一种Delete Mark操作,在记录上标识删除,真正的删除工作需要后台purge线程去完成。




Read View(读视图)


什么是Read View


Read View就是事务进行快照读操作的时候生产的读视图(Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的快照,记录并维护系统当前活跃事务的ID(当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以最新的事务,ID值越大)



作用


Read View主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个Read View读视图,把它用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。



核心算法(可见性算法)


Read View的三个属性


  • trx_ids: 一个数值列表,用来维护Read View生成时刻系统正活跃的事务ID


  • up_limit_id:记录trx_ids列表中事务ID最小的ID


  • low_limit_id:ReadView生成时刻系统尚未分配的下一个事务ID,也就是目前已出现过的事务ID的最大值+1



可见性判断的流程


遍历DB_TRX_ID执行以下步骤,直到找到当前事务可见的最新数据:
复制代码


  遍历方法:如果当前DB_TRX_ID这条记录不满足当前事务的可见性,可通过这条记录的DB_ROLL_PTR回滚指针去取出undo log中前一个版本的DB_TRX_ID


step1:比较DB_TRX_ID小于up_limit_id


 如果小于,则当前事务能看到DB_TRX_ID所在的记录;即该记录是可见的最新的记录如果大于等于进入step2。


step2:判断 DB_TRX_ID 大于等于 low_limit_id


 如果大于等于则代表DB_TRX_ID所在的记录在Read View生成后才出现的,那对当前事务肯定不可见,继续遍历下一个DB_TRX_ID如果小于则进入step3


step3:判断DB_TRX_ID 是否在活跃事务之中


  如果在,则代表当前事务的Read View生成时刻,DB_TRX_ID这个事务还在活跃,还没有Commit,DB_TRX_ID这个事务修改的数据,当前事务也是看不见的;


即对当前事务不可见,继续遍历下一个DB_TRX_ID,如果不在,则说明,DB_TRX_ID这个事务在当前事务的Read View生成之前就已经Commit了,DB_TRX_ID这个事务修改的结果,对于当前事务是可见的




MVCC的工作原理


MVCC查询的工作流程


查询主键索引


  1. 生成Read View读视图


  1. 通过主键查找记录,根据记录里的DB_TRX_ID与Read View读视图进行可见性判断


  1. 配合DB_ROLL_PTR回滚指针和undo log来找到当前事务可见的数据记录



查询二级索引


  1. 生成Read View读视图


  1. 比较读视图的up_limit_id与MAX_TRX_ID大小


  1. 如果MAX_TRX_ID小于本次Read View的up_limit_id,则全部可见,过滤记录中的有效记录否则,无法通过二级索引判断可见性,需要一次遍历每条记录,反查到聚簇索引记录,通过聚簇索引记录来判断可见性




MVCC与隔离级别


MVCC只在Read Commited和Repeatable Read两种隔离级别下工作。
复制代码
  • 在RC隔离级别下,是每个快照读都会生成并获取最新的Read View,这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因


  • 在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View。


RR级别下,快照读生成Read View时,Read View会记录此时所有其他活动事务的快照,这些事务的修改对于当前事务都是不可见的。而早于Read View创建的事务所做的修改均是可见。

image.png





相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
7天前
|
缓存 关系型数据库 MySQL
MySQL并发支撑底层Buffer Pool机制详解
【10月更文挑战第18天】在数据库系统中,磁盘IO操作是性能瓶颈之一。为了提高数据访问速度,减少磁盘IO,MySQL引入了缓存机制。其中,Buffer Pool是InnoDB存储引擎中用于缓存磁盘上的数据页和索引页的内存区域。通过缓存频繁访问的数据和索引,Buffer Pool能够显著提高数据库的读写性能。
35 2
|
1天前
|
存储 关系型数据库 MySQL
MySQL主从复制原理和使用
本文介绍了MySQL主从复制的基本概念、原理及其实现方法,详细讲解了一主两从的架构设计,以及三种常见的复制模式(全同步、异步、半同步)的特点与适用场景。此外,文章还提供了Spring Boot环境下配置主从复制的具体代码示例,包括数据源配置、上下文切换、路由实现及切面编程等内容,帮助读者理解如何在实际项目中实现数据库的读写分离。
MySQL主从复制原理和使用
|
1天前
|
SQL 关系型数据库 MySQL
Mysql中搭建主从复制原理和配置
主从复制在数据库管理中广泛应用,主要优点包括提高性能、实现高可用性、数据备份及灾难恢复。通过读写分离、从服务器接管、实时备份和地理分布等机制,有效增强系统的稳定性和数据安全性。主从复制涉及I/O线程和SQL线程,前者负责日志传输,后者负责日志应用,确保数据同步。配置过程中需开启二进制日志、设置唯一服务器ID,并创建复制用户,通过CHANGE MASTER TO命令配置从服务器连接主服务器,实现数据同步。实验部分展示了如何在两台CentOS 7服务器上配置MySQL 5.7主从复制,包括关闭防火墙、配置静态IP、设置域名解析、配置主从服务器、启动复制及验证同步效果。
Mysql中搭建主从复制原理和配置
|
5天前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
12 1
|
9天前
|
存储 自然语言处理 关系型数据库
mysql 8.0 日期维度表生成(可运行)
mysql 8.0 日期维度表生成(可运行)
28 2
|
9天前
|
SQL 关系型数据库 MySQL
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
尼恩,一位40岁的资深架构师,通过其丰富的经验和深厚的技術功底,为众多读者提供了宝贵的面试指导和技术分享。在他的读者交流群中,许多小伙伴获得了来自一线互联网企业的面试机会,并成功应对了诸如事务ACID特性实现、MVCC等相关面试题。尼恩特别整理了这些常见面试题的系统化解答,形成了《MVCC 学习圣经:一次穿透MYSQL MVCC》PDF文档,旨在帮助大家在面试中展示出扎实的技术功底,提高面试成功率。此外,他还编写了《尼恩Java面试宝典》等资料,涵盖了大量面试题和答案,帮助读者全面提升技术面试的表现。这些资料不仅内容详实,而且持续更新,是求职者备战技术面试的宝贵资源。
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
|
9天前
|
存储 关系型数据库 MySQL
mysql 8.0 时间维度表生成(可运行)
mysql 8.0 时间维度表生成(可运行)
24 0
|
13天前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
61 6
|
11天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
45 3
Mysql(4)—数据库索引
|
13天前
|
SQL Ubuntu 关系型数据库
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
本文为MySQL学习笔记,介绍了数据库的基本概念,包括行、列、主键等,并解释了C/S和B/S架构以及SQL语言的分类。接着,指导如何在Windows和Ubuntu系统上安装MySQL,并提供了启动、停止和重启服务的命令。文章还涵盖了Navicat的使用,包括安装、登录和新建表格等步骤。最后,介绍了MySQL中的数据类型和字段约束,如主键、外键、非空和唯一等。
48 3
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用