基于MVCC,我用C++自己手撸了个MySQL!!

简介: 基于MVCC,我用C++自己手撸了个MySQL!!


大家好,我是冰河~~

没错,真如标题所示,我基于MVCC算法(这里我姑且叫它算法吧,毕竟在实际写代码时,确实是利用算法实现的),使用C++写了个简易版的MySQL,实现了简易版的CRUD操作。

其实,今天我并不打算先向小伙伴们演示我写的简易版MySQL,这个项目待我再优化下,会开源出来的,到时大家可以一起学习,一起进步,一起来维护它。

今天,我想跟大家重点聊聊MVCC,网上关于MVCC的文章很多,大部分都是基于版本链进行介绍的,其实对于初学者来说,使用版本链介绍MVCC其实还是挺难理解的。今天,我就来跟大家聊聊我是如何理解MVCC的,MVCC其实很简单,不用版本链你也可以彻底理解透彻。

MVCC技术

MVCC是一种通过记录数据的历史版本来提升事务并发处理能力的一项技术,它能够极大的提升在并发事务下数据的处理性能,目前,大部分关系型数据库都实现了MVCC机制。

MVCC主要解决多事务并发控制问题,也就是保证事务的隔离性。

MVCC的存储方式

MVCC大体上可以分为三种存储方式,分别为Append-Only方式、Delta方式和Time-Travle方式,如下所示。

(1)Append-Only方式:将数据的历史版本直接存储在数据表中,代表数据库为PostgreSQL。

(2)Delta方式:将数据的增量历史版本存储在独立的表空间,代表数据库为MySQL和Oracle。

(3)Time-Travle方式:将数据的每个版本都全量存储下来,代表数据库为HANA。

MVCC的工作原理

MVCC主要用来保证事务的隔离性,这里,我们就分别以读已提交和可重复读两种隔离级别为例,来聊聊MVCC是如何工作的。

读已提交MVCC的工作原理

在读已提交隔离级别下,当前事务只能看到两类数据,如下所示。

(1)当前事务自身产生的数据。

(2)当前事务开启之前,其他已经提交的事务所产生的数据。

为了便于小伙伴们理解,这里我画了一张简易的事务执行图,如下所示。

图片.png


事务A到事务E是在数据库中执行的五个事务,它们按照先后顺序执行,分别操作的是数据表中data1~data5的五条记录。在t1时刻,启动事务E,事务E要读取事务A到事务D的这四条记录,在t1时刻,事务E启动时,会向系统申请一个活动事务列表,所谓的活动事务,就是已经启动但是并未提交或者回滚的事务。

所以,在申请的活动事务列表中会看到事务D,当事务E查询到data4这条数据记录时,其对应的事务D正好在活动事务列表中,事务E就会读取data4的上一个版本。

而事务A、事务B和事务C在事务E启动时已经提交,并且最新版本的事务id小于活动事务D对应的事务id,所以事务E能够看到事务A、事务B和事务C对应的data1、data2和data3记录的最新版本。

可重复读MVCC的工作原理

在重复读隔离级别下,MVCC又是如何工作的呢?先来看张图。

图片.png


如果在读已提交隔离级别下,则在t1时刻,事务E启动时,事务A、事务B和事务C已经提交,所以,事务E能够读取到事务A、事务B和事务C对应的data1、data2和data3记录的最新版本。而事务D属于活动事务,所以,事务E能够读取到data4的上一个版本。

事务E执行到t2时刻时,事务D也已经提交,按照之前的分析可知,在t2时刻,事务E能够读取到事务A、事务B、事务C和事务D对应的数据data1、data2、data3和data4的最新版本。

在可重复读隔离级别下,这显然是不符合要求的。

在可重复读隔离级别下,MVCC机制是如何解决这个问题的呢?

其实解决的办法很简单,就是在系统中记录下t1时刻启动事务E时的活动事务列表,在事务E执行的过程中,一直使用在t1时刻记录的活动事务列表即可,这个一直使用的活动事务列表被称为“快照”。

很显然,在t2时刻使用在t1时刻保存的活动事务列表,则事务E在t1时刻和t2时刻读取到的数据是一致性。

读已提交与可重复读MVCC的区别

读已提交隔离级别下每个SQL语句都会有一个自己的快照,它们看到的数据库中的数据是不同的。而在可重复读隔离级别下,所有的SQL语句使用同一个快照,能够看到数据库中同样的数据。

快照优化

在实现MVCC时,并只是简单的存储事务id列表,而是会统计最小活动事务id和最大已提交事务id,这样做的好处是:大部分事务id通过比较这些边界值就能够迅速判别是读取最新版本还是上一个版本,如果事务id正好落在这些边界值的范围之内,则只需要进一步查找当前事务id是否与活动事务的id相匹配即可。如果相匹配,则说明当前事务是活动事务,可以看到当前数据。

好了,关于MVCC,小伙伴们,你们理解了吗?理解透彻后,再学习下MySQL的底层原理,有条件的话,阅读下MySQL的源码,然后跟冰河一起手写MySQL。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
存储 关系型数据库 MySQL
Linux C/C++ 开发(学习笔记八):Mysql数据库图片存储
Linux C/C++ 开发(学习笔记八):Mysql数据库图片存储
276 0
|
10月前
|
数据可视化 关系型数据库 MySQL
嵌入式C++、STM32、MySQL、GPS、InfluxDB和MQTT协议数据可视化
通过本文的介绍,我们详细讲解了如何结合嵌入式C++、STM32、MySQL、GPS、InfluxDB和MQTT协议,实现数据的采集、传输、存储和可视化。这种架构在物联网项目中非常常见,可以有效地处理和展示实时数据。希望本文能帮助您更好地理解和应用这些技术,构建高效、可靠的数据处理和可视化系统。
578 82
|
SQL 关系型数据库 MySQL
C++orm使用插曲——MySQL保留字
C++orm使用插曲——MySQL保留字
137 7
|
SQL 关系型数据库 MySQL
使用 C++ 结合 MySQL 数据库实现留言板
使用 C++ 结合 MySQL 数据库实现留言板
241 1
|
NoSQL 关系型数据库 MySQL
Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)
Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)
1182 0
|
网络协议 关系型数据库 MySQL
[mysql 基于C++实现数据库连接池 连接池的使用] 持续更新中
[mysql 基于C++实现数据库连接池 连接池的使用] 持续更新中
|
关系型数据库 MySQL C++
[mysql C++ 简单连接到深入] 持续更新中
[mysql C++ 简单连接到深入] 持续更新中
|
3月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
160 3
|
3月前
|
关系型数据库 MySQL 数据库
自建数据库如何迁移至RDS MySQL实例
数据库迁移是一项复杂且耗时的工程,需考虑数据安全、完整性及业务中断影响。使用阿里云数据传输服务DTS,可快速、平滑完成迁移任务,将应用停机时间降至分钟级。您还可通过全量备份自建数据库并恢复至RDS MySQL实例,实现间接迁移上云。
|
3月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
783 152