MySQL相关(六)- 事务隔离级别的实现方案(MVCC)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL相关(六)- 事务隔离级别的实现方案(MVCC)


正文中的絮絮叨叨

我们大家先思考一下,如果要解决读一致性的问题,保证一个事务中前后两次读取数据结果一致,实现事务隔离,应该怎么做?我们有哪一些方法呢?你的思路是什么样的呢?

总体上来说,我们有两大类的方案。

LBCC

第一种,我既然要保证前后两次读取数据一致,那么我读取数据的时候,锁定我要操作的数据,不允许其他的事务修改就行了。这种方案我们叫做基于锁的并发控制 Lock Based Concurrency Control(LBCC)。

如果仅仅是基于锁来实现事务隔离,一个事务读取的时候不允许其他时候修改,那就意味着不支持并发的读写操作,而我们的大多数应用都是读多写少的,这样会极大地影响操作数据的效率。

MVCC

所以我们还有另一种解决方案,如果要让一个事务前后两次读取的数据保持一致,那么我们可以在修改数据的时候给它建立一个备份或者叫快照,后面再来读取这个快照就行了。这种方案我们叫做多版本的并发控制 Multi Version Concurrency Control (MVCC)。

MVCC 的核心思想是: 我可以查到在我这个事务开始之前已经存在的数据,即使它在后面被修改或者删除了。在我这个事务之后新增的数据,我是查不到的。

  • 问题:这个快照什么时候创建?读取数据的时候,怎么保证能读取到这个快照而不是最新的数据?这个怎么实现呢?

InnoDB 为每行记录都实现了两个隐藏字段:

DB_TRX_ID,6 字节:插入或更新行的最后一个事务的事务 ID,事务编号是自动递增的(我们把它理解为创建版本号,在数据新增或者修改为新数据的时候,记录当前事务 ID)。

DB_ROLL_PTR,7 字节:回滚指针(我们把它理解为删除版本号,数据被删除或记录为旧数据的时候,记录当前事务 ID)。

我们把这两个事务 ID 理解为版本号。

第一个事务,初始化数据(检查初始数据)

//Transaction 1
begin;
insert into mvcctest values(NULL,'Jerry') ;
insert into mvcctest values(NULL,'jack') ;
commit;
复制代码

此时的数据,创建版本是当前事务 ID,删除版本为空:

id name 创建版本 删除版本
1 Jerry 1 undefined
2 jack 1 undefined

第二个事务,执行第 1 次查询,读取到两条原始数据,这个时候事务 ID 是 2:

// Transaction 2
begin;
select * from mvcctest ;  -- (1) 第一次查询
复制代码

第三个事务,插入数据:

// Transaction 3
begin;
insert into mvcctest values(NULL,'tom') ;
commit;
复制代码

此时的数据,多了一条 tom,它的创建版本号是当前事务编号,3:

id name 创建版本 删除版本
1 Jerry 1 undefined
2 jack 1 undefined
3 tom 3 undefined

第二个事务,执行第 2 次查询:

Transaction 2
select * from mvcctest ;  (2) 第二次查询
复制代码

MVCC 的查找规则:只能查找创建时间小于等于当前事务 ID 的数据,和删除时间大于当前事务 ID 的行(或未删除)。

也就是不能查到在我的事务开始之后插入的数据,tom 的创建 ID 大于 2,所以还是只能查到两条数据。

第四个事务,删除数据,删除了 id=2 jack 这条记录:

Transaction 4
begin;
delete from mvcctest where id=2;
commit;
复制代码

此时的数据,jack 的删除版本被记录为当前事务 ID,4,其他数据不变:

id name 创建版本 删除版本
1 Jerry 1 undefined
2 jack 1 4
3 tom 3 undefined

在第二个事务中,执行第 3 次查询:

Transaction 2
select * from mvcctest ;  (3) 第三次查询
复制代码

查找规则:只能查找创建时间小于等于当前事务 ID 的数据,和删除时间大于当前事务 ID 的行(或未删除)。

也就是,在我事务开始之后删除的数据,所以 jack 依然可以查出来。所以还是这两条数据。

第五个事务,执行更新操作,这个事务事务 ID 是 5:

Transaction 4
begin;
update mvcctest set name ='Mic' where id=1;
commit;
复制代码

此时的数据,更新数据的时候,旧数据的删除版本被记录为当前事务 ID 5(undo),产生了一条新数据,创建 ID 为当前事务 ID 5:

id name 创建版本 删除版本
1 Jerry 1 5
2 jack 1 4
3 tom 3 undefined
1 Mic 5 undefined

第二个事务,执行第 4 次查询:

// Transaction 2
select * from mvcctest ;  (4) 第四次查询
复制代码

查找规则:只能查找创建时间小于等于当前事务 ID 的数据,和删除时间大于当前事务 ID 的行(或未删除)。

因为更新后的数据 Mic 创建版本大于 2,代表是在事务之后增加的,查不出来。

而旧数据 Jerry 的删除版本大于 2,代表是在事务之后删除的,可以查出来。

通过以上演示我们能看到,通过版本号的控制,无论其他事务是插入、修改、删除,第一个事务查询到的数据都没有变化。

在 InnoDB 中,MVCC 是通过 Undo log 实现的。

Oracle、Postgres 等等其他数据库都有 MVCC 的实现。

需要注意,在 InnoDB 中,MVCC 和锁是协同使用的,这两种方案并不是互斥的。第一大类解决方案是锁,锁又是怎么实现读一致性的呢?

关于锁的知识已经在快马加鞭准备了,且听下回分解~




相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
4天前
|
SQL 存储 缓存
【MySQL】事务
【MySQL】事务
13 0
|
5天前
|
SQL 存储 关系型数据库
MySQL索引及事务
MySQL索引及事务
24 2
|
5天前
|
存储 关系型数据库 MySQL
MySQL事务简述
MySQL事务简述
6 0
|
5天前
|
存储 算法 关系型数据库
MySQL事务与锁,看这一篇就够了!
MySQL事务与锁,看这一篇就够了!
|
5天前
|
Java 关系型数据库 MySQL
MySQL 索引事务
MySQL 索引事务
13 0
|
5天前
|
安全 关系型数据库 MySQL
CentOS 7系统加固详细方案SSH FTP MYSQL加固
CentOS 7系统加固详细方案SSH FTP MYSQL加固
|
5天前
|
SQL 安全 关系型数据库
【Mysql-12】一文解读【事务】-【基本操作/四大特性/并发事务问题/事务隔离级别】
【Mysql-12】一文解读【事务】-【基本操作/四大特性/并发事务问题/事务隔离级别】
|
5天前
|
存储 关系型数据库 MySQL
Mysql学习--深入探究索引和事务的重点要点与考点
Mysql学习--深入探究索引和事务的重点要点与考点
|
5天前
|
存储 SQL 关系型数据库
Mysql_数据库事务
Mysql_数据库事务
|
5天前
|
缓存 关系型数据库 MySQL
【专栏】提升MySQL性能和高可用性的策略,包括索引优化、查询优化和事务管理
【4月更文挑战第27天】本文探讨了提升MySQL性能和高可用性的策略,包括索引优化、查询优化和事务管理。通过合理使用B-Tree和哈希索引,避免过度索引,以及优化查询语句和利用查询缓存,可以改善性能。事务管理中,应减小事务大小并及时提交,以保持系统效率。主从或双主复制可增强高可用性。综合运用这些方法,并根据实际需求调整,是优化MySQL的关键。

推荐镜像

更多
http://www.vxiaotou.com