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

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 基于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。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
存储 关系型数据库 MySQL
Linux C/C++ 开发(学习笔记八):Mysql数据库图片存储
Linux C/C++ 开发(学习笔记八):Mysql数据库图片存储
47 0
|
3月前
|
关系型数据库 MySQL 数据库
Linux C/C++ 开发(学习笔记七):Mysql数据库C/C++编程实现 插入/读取/删除
Linux C/C++ 开发(学习笔记七):Mysql数据库C/C++编程实现 插入/读取/删除
49 0
|
8月前
|
关系型数据库 MySQL 编译器
DEVC++的C语言连接数据库mysql
DEVC++的C语言连接数据库mysql
233 0
|
30天前
|
NoSQL 关系型数据库 MySQL
Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)
Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)
193 0
|
3月前
|
网络协议 关系型数据库 MySQL
[mysql 基于C++实现数据库连接池 连接池的使用] 持续更新中
[mysql 基于C++实现数据库连接池 连接池的使用] 持续更新中
|
3月前
|
关系型数据库 MySQL C++
[mysql C++ 简单连接到深入] 持续更新中
[mysql C++ 简单连接到深入] 持续更新中
|
3月前
|
关系型数据库 MySQL Linux
Linux C/C++ 开发(学习笔记六):MySQL安装与远程连接
Linux C/C++ 开发(学习笔记六):MySQL安装与远程连接
46 0
|
5月前
|
C++
BQ云盘项目一 -- nginx+fastcgi+fastdfs+mysql+redis+c/c++
BQ云盘项目一 -- nginx+fastcgi+fastdfs+mysql+redis+c/c++
|
5月前
|
SQL 关系型数据库 MySQL
8、Linux C/C++ 实现MySQL的图片插入以及图片的读取
8、Linux C/C++ 实现MySQL的图片插入以及图片的读取
42 0
|
5月前
|
关系型数据库 MySQL Java
C++实战-基于c++11新特性的mysql连接池
C++实战-基于c++11新特性的mysql连接池
42 0