MYSQL的多版本并发控制MVCC(Multi-Version Concurrency Control)

2023-09-20 22:45:00

1、概述

MVCC是一种用于数据库管理系统的并发控制技术,允许多个事务同时访问数据库,而不会导致读写冲突。也就是说在读写的时候,线程不用去争抢读写锁。因为加锁的过程比较耗性能。
当然很多时候还是必须的,不能避免,比如说,去ATM机取钱的时候,同时又在手机APP上进行提现,这种操作就需要加锁,不能让其同时提现,一次只能一个操作,而且只有在ATM取钱这个事务被提交之后才能做其他操作。

处理并发的场景无外乎三种:

读、读:这个不需要做控制,因为数据没有变化
读、写:存在线程安全问题,可能出现脏读、幻读,不可重复读
写、写:存在线程安全问题,可能出现更新丢失的情况

这里介绍的MVCC是在存储引擎为InnoDB实现的,目的也是为了提高数据库的并发性能,不使用加锁的方式去处理读、写并发。

2、MVCC特点

这里的读操作,有两种方式:
快照读:SELECT语句,在读写的时候不用加锁,所以效率很高,但也存在读取的时候有更新操作,可能会读到历史数据。

当前读:读取的是最新数据,是一种悲观锁的操作。它会对当前读取的数据进行加锁,避免其他事物对其进行写操作。主要包括以下几种操作:

select lock in share mode(共享锁)
select for update(排他锁)
update(排他锁)
insert(排他锁)
delete(排他锁)

3、准备数据

在介绍之前,没有安装MYSQL的,可以先进行安装,下载地址:https://dev.mysql.com/downloads/
安装好了之后,我们就新建库与表,插入一些数据来做个测试

CREATE DATABASE mydb;
USE mydb;

CREATE TABLE `tb1` (
  `id` int(12) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;

INSERT INTO tb1(name) VALUES ('XIAO1'),('XIAO2'),('XIAO3');

CREATE TABLE `tb2` (
  `id` int(12) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=myisam;

INSERT INTO tb2(name) VALUES ('LAO1'),('LAO2'),('LAO3');

这里我特地创建了两张表,分别是表tb1对应的是InnoDB引擎,表tb2对应的是myisam引擎,创建之后,也可以看到两者的数据格式也是不一样的,我们先查询下,新建的数据库mydb以及保存的数据在什么地方:

mysql> show variables like '%datadir%';
+---------------+---------------------------------------------+
| Variable_name | Value                                       |
+---------------+---------------------------------------------+
| datadir       | C:\ProgramData\MySQL\MySQL Server 8.0\Data\ |
+---------------+---------------------------------------------+
1 row in set, 1 warning (0.00 sec)

然后可以看到,InnoDB引擎对应的是:tb1.ibd myisam对应的是:tb2.MYD(数据)、tb2.MYI(索引)、tb2_402.sdi(表结构)[这个在以前的版本没有出现]
MySQL5.5之后都是默认为InnoDB引擎

4、MVCC原理

MYSQL存储的数据中,除了我们显式定义的字段,还隐含着两个字段。
trx_id:事务id,每进行一次事务操作,就会自增1。
roll_pointer:回滚指针,用于找到上一个版本的数据,结合undolog进行回滚。


我们用SELECT读数据时,这一时刻的数据会有很多个版本【比如上图四个版本】,但我们并不知道读取哪个版本,依赖ReadView来对我们进行版本的选择,通过ReadView我们就能够知道读取哪个版本。我们来看下这个ReadView的定义:

class ReadView {
/* ... */
private:
trx_id_t m_low_limit_id; /* 大于等于这个 ID 的事务均不可见 */

trx_id_t m_up_limit_id; /* 小于这个 ID 的事务均可见 */

trx_id_t m_creator_trx_id; /* 创建该 Read View 的事务ID */

trx_id_t m_low_limit_no; /* 事务 Number, 小于该 Number 的 Undo Logs 均可以被 Purge */

ids_t m_ids; /* 创建 Read View 时的活跃事务列表 */

m_closed; /* 标记 Read View 是否 close */
}

字段的解释:

m_low_limit_id:目前出现的最大事务ID+1(下一个将被分配的事务ID)。大于等于这个ID的数据版本均不可见,也就访问不到。

m_up_limit_id:活跃事务列表m_ids中最小的事务ID,如果为空,则m_up_limit_id为m_low_limit_id。小于这个ID的数据版本均可见。

m_ids:ReadView创建时其他未提交的活跃事务ID列表。创建ReadView时,将当前未提交事务ID记录下来,后续即使它们修改了记录行的值,对于当前事务也是不可见的。m_ids 不包括当前事务自己和已提交的事务(正在内存中)

m_creator_trx_id:创建该ReadView的事务ID

5、实践操作

开四个终端,新建三个事务,两个写操作,一个读操作,还有一个就是单纯的查询。大家可以根据不同的进入时间来了解这个过程,会产生未提交和已提交事务状态,对应的查询信息都是不一样的,具体代码分别如下:

BEGIN;
UPDATE tb1 SET  name='XXX' WHERE id=1;
UPDATE tb1 SET  name='YYY' WHERE id=1;
COMMIT;

BEGIN;
UPDATE tb1 SET  name='ZZZ' WHERE id=1;
UPDATE tb1 SET  name='QQQ' WHERE id=1;
DELETE FROM tb1 WHERE id=5;
COMMIT;

BEGIN;
SELECT * FROM tb1 WHERE id=1;
COMMIT;

SELECT * FROM tb1;

6、小结

对于这种读写并发,以及对性能的要求,大家需要看实际业务情况来做决定,其中这里主要是介绍InnoDB引擎,这个要高效很多,在以前的旧版本可能大家使用MyISAM这个更多,因为性能很好,不过不支持事务操作,所以很多场景也就不适应,MYSQL5.5版本之后就是默认InnoDB引擎了。
最后大家也可以尝试在表tb2中去尝试下,看下是什么结果,因为这张表使用的是MyISAM引擎,就起不到作用了。
另外需要注意的是,事务的提交是默认自动的,有些时候需要关闭,将默认的1修改为0:

SET AUTOCOMMIT=0;
SELECT @@AUTOCOMMIT;

比如说对于脏读的情况,我们需要当前读,也就是需要排它锁:

SET AUTOCOMMIT=0;
BEIGIN;
DELETE FROM tb1 WHERE id=2;

这种情况如果我们的事务在这个时候进去,对这个id=2进行读写操作,就会出现脏读的情况,这个时候就需要使用SELECT FOR UPDATE,等待事务处理完毕之后再做相应的操作。

对于脏读这种情况,很常见,比如说事务在做删除操作,这个时候记录已被删除但是还没有提交事务,如果进行查询操作就会出现脏读,如下:

SET AUTOCOMMIT=0;
BEGIN;
SELECT * FROM tb1 WHERE id=2 FOR UPDATE;
UPDATE tb1 SET  name='QQQ' WHERE id=1;
COMMIT;
更多推荐

计算机视觉与深度学习-卷积神经网络-纹理表示&卷积神经网络-纹理表示-[北邮鲁鹏]

目录标题参考文章纹理定义纹理的分类规则纹理随机纹理纹理的表示方法基于卷积核组思路什么卷积核组卷积核类型(边缘、条形、点状)卷积核尺度(3~6个尺度)卷积核的方向卷积核组的设计表示步骤步骤一:设计卷积核组。步骤二:利用卷积核组对图像进行卷积操作获得对应的特征响应图组。步骤三:利用特征响应图的某种统计信息来表示图像中的纹理

计算机视觉(CV)技术

计算机视觉(CV)技术的优势:1.自动化和效率:计算机视觉可以自动地完成冗长和繁重的任务,并且可以实现高效率的数据处理。2.准确性:计算机视觉使用数学算法和模型进行数据分析,可以实现高准确性的结果,同时还可以通过学习算法改进准确性。3.可视化:计算机视觉可以将数据可视化,可以让人类更好地理解数据。4.非接触性:计算机视

Nuxt 菜鸟入门学习笔记:路由

文章目录路由Routing页面Pages导航Navigation路由参数RouteParameters路由中间件RouteMiddleware路由验证RouteValidationNuxt官网地址:https://nuxt.com/路由RoutingNuxt的一个核心功能是文件系统路由器。pages/目录下的每个Vue

大数据运维一些常见批量操作命令

大数据运维中,批量操作是一项常见的任务。在使用flume进行数据采集的过程中,有时会出现故障导致采集停止,此时积累了大量的文件。如果想要将这些文件迁移到新的目录,直接使用"mv"命令可能会因为文件数目过多而报错。为了解决这个问题,我们可以利用管道技术和"xargs"命令。"xargs"是一个用于给命令传递参数的过滤器,

【React】面试题5题

1.说说你对dangerouslySetInnerHTML的理解dangerouslySetInnerHTML是React中的一个属性,用于将HTML代码作为字符串直接插入到组件中的DOM元素中。它可以用来动态地生成HTML内容,但同时也带来了一些潜在的安全风险。使用dangerouslySetInnerHTML时,需

Gartner 公布 2023新兴技术成熟度曲线,AI依然是全村的希望,从云端到边缘延伸...

边缘计算社区从Gartner官网了解到,近日,Gartner公布了2023年新兴技术成熟度曲线以及最新的技术趋势。2023新兴技术成熟度曲线2023年Gartner技术成熟度曲线确定了25项值得关注的新兴技术,它们将为企业架构和技术创新领导者提供助力。这些技术有望在未来2-10年内对商业及社会产生显著影响。使CIO和I

Windows环境变量 和 Linux环境变量

环境变量就像是一张地图,告诉程序员和程序在哪里可以找到所需的资源和工具。🗺🗺一、Windows环境变量1.1什么是Windows环境变量?1.2Windows环境变量的设置和访问1.21设置环境变量1.22查看环境变量1.3常见的Windows环境变量1.4环境变量的作用1.5Windows环境变量长度限制问题二、

【C# 基础精讲】List 集合的使用

在C#中,List<T>是一种非常常用的泛型集合类,用于存储一组相同类型的元素。List<T>具有动态调整大小的能力,可以方便地添加、删除、查找和修改元素,非常灵活和高效。本文将详细介绍List<T>集合的使用方法,包括创建List<T>对象、添加元素、删除元素、查找元素、遍历集合以及常用的List<T>方法等内容。1

RockyLinux9.2 网卡配置和nmcli、nmtui命令的使用

NetworkManagerNetworkManager是一个标准的Linux网络配置工具套件,支持服务器,也支持桌面环境,发展到如今,绝大多数流行的发行版都支持它。这套网络配置工具适用于RockyLinux8及更高版本。nmcli是nm的命令行工具、nmtui是nm的ui工具nmcli查看网络信息ipa或者nmcli

Linux文件内容查看和编辑指南:cat、less、grep等常用命令详解

文章目录Linux文件内容查看和编辑1.查看文件内容cat用法cat详解概要主要用途参数选项返回值例子注意lessless详解补充说明语法选项参数实例moremore详解补充说明语法选项参数实例2.文件搜索和过滤grepgrep详解语法选项参数实例findfind详解语法选项参数实例awkawk详解语法选项参数实例3.

深入浅出之数组

深入浅出之数组文章目录:深入浅出之数组一、数组的基本语法1.1数组声明1.2数组初始化二、多维数组2.1多维数组的基本语法2.2多维数组的适用场景三、数组的实际练习(传智杯真题为例)一、数组的基本语法1.1数组声明数组声明通常为valuename[number]的形式。value是值得数据类型,name是数组名称,nu

热文推荐