到底什么是Mysql的MVCC

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 到底什么是Mysql的MVCC

想要说什么是MVCC,得先从数据库的隔离级别说起,我们都知道数据库的隔离级别有四种,分别是读已提交,读未提交,重复读,串行化

我们需要根据自己的场景来选择合适的隔离级别

隔离级别         脏读         不可重复读       幻影读

读未提交          √               √                     √

读已提交          ×               √                      √

重复读              ×              ×                      √

串行化             ×               ×                      ×

事务的四大特性

acid

原子性undo log

一致性 最核心的本质要求

隔离性 锁 MVCC

持久性 redo log

下面是四种级别的详细解释

未授权读取

也称为读未提交(Read Uncommitted):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。

授权读取

也称为读提交(Read Committed):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。

可重复读取(Repeatable Read)

可重复读取(Repeatable Read):禁止不可重复读取和脏读取,但是有时可能出现幻读数据。这可以通过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。

序列化(Serializable)

序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

MVCC 多版本并发控制

什么是MVCC

1, MVCC

MVCC, 全称Muli-Ver sion Concurrency Control,即多版本井发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,

实现对数据库的并发访问,在编程语言中实现事务内存。

MVCC在My SQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读写冲突,做到即使有读写冲突时,也能做到不加锁,

非阻寒并发读。

2、当前读

像select lock in share mode(共享锁), select for update ; update, insert,delete(排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。

3、快照读

像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

4、当前读、快照读、MVCC关系

MVCC多版本并发控制指的是维持一个数据的多个版本,使得读写操作没有冲突,快照读是MySQL为实现MVCC的一个非阻塞读功能,MVCC模块在MySQL中的具体实现是由三个 隐式字段,undo日志、read view三个组件来实现的。

5、MVCC解决的问题

数据库并发场是有三种,分别为:

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

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

3、写写: 有线程安全问题,可能存在更新丢失问题

MVC(是一种用来解次读写冲突的无锁并发控制,也就是为事务分配单项增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照,所以MVCC可以为数据库解决一下问题!

1、在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能

2、解决脏读、不可重复读、幻读等事务隔离问题,但是不能解决更新丢失问题

6、MVCC实现原理

mvcc的实现原理主要依赖于记录中的三个 隐藏字段undologread view来实现的。

隐藏字段

每行记录除了我们自定义的字段外,还有数据库隐式定义的DB_TRX ID,DB_ROLL_PTR,DB_ROWID等字段

DB TRX ID

6字节,最近修改事务id,记录创建这条记录或者最后一次修改该记录的事务id

DB ROLL PTR

7字节,回滚指针,指向这条记录的上一个版本,用于配合undolog,指向上一个旧版本

DB_ROWID

6字节,隐藏的主键,如果数据表没有主键,那么innodb会自动生成一个6字节的row_id

记录如图所示:

在上图中,DB_ROWID是数据库默认为该行记录生成的唯一隔式主建,DBTRX ID是当前操作该记录的事务ID,DB ROLLPTR是一个回滚指针,用于配合undo日志,指向上一个日版本

undo log

undolog被称之为回滚日志,表示在进行insert,delete,update操作的时候产生的方便回淡的日志当进行insert操作的时候,产生的unddlog只在事务回滚的时候需要,并且在事务提交之后可以被立刻丢弃

当进行update和delete操作的时候,产生的undolor不仅仅在事务回滚的时候需要,在快照读的时候也需要,所以不能随便删除,只在快照读或事务回滚不涉及该日志时,对应的日志才会被puree线程统一清除(当数据发生更新和删 除操作的时候都只是设置一下者记灵的deleted bt,并不是真正的将过时的记录删除,因为为了节省磁盘空间,innodb有专门的purge线程来清除deleted bit为true的记,如果某个记录的deleted id为true,并且DB_TRX ID对于purge线程的read view 可见,那么这条记录一定时可以被清除的

下面我们来看一下undolog生成的记录链

1、假设有一个事务编号为1的事务向表中插入一条记录,那么此时行数据的状态为:

2、假设有第二个事务编号为2对该记录的name做出修改,改为lisi在事务2修改该行记录数据时,数据库会对该行加排他锁

然后把该行数据拷贝到undolog中,作为旧记录,即在undolog中有当前行的拷贝副本拷贝完毕后,修改该行name为lisi,并且修改隐藏字段的事务id为当前事务2的id,回滚指针指向拷贝到undolog的副本记录中事务提交后,释放锁

3、假设有第三个事务编号为3对该记录的age做了修改,改为32

在事务3修改该行数据的时,数据库会对该行加排他锁

然后把该行数据拷贝到undolog中,作为旧纪录,发现该行记录已经有undolog了,那么最新的旧数据作为链表的表头,插在该行记录的undolog最前面

修改该行age为32岁,并且修改隐藏字段的事务id为当前事务3的id,回滚指针指向刚刚拷贝的undolog的副本记录

事务提交,释放锁  

即链表,undolog的链首就是最新的旧记录,链尾就是最早的旧记录

从上述的一系列图中,大家可以发现,不同事务或者相同事务的对同一记录的修改,会导致该记录的undolog生成一条记录版本线性

Read View(可见性判断)

上面的流程如果看明白了,那么大家需要再深入理解下read view的概念了

Read view是事务进行快照读操作的时候生产的读视图,在该事务执行快照读的那一刻,会生成一个数据系统当前的快照,记录并维护系统当前活跃事务的id,事务的id值是递增的。其实Read View的最大作用是用来做可见性判断的,也就是说当某个事务在执行快照读的时候,对该记录创建一个Read View的视图,把它当作条件去判断当前事务能够看到哪个版本的数据,有可能读取到的是最新的数据,也有可能读的是当前行记录的undolog中某个版本的数据

Read View遵循的可见性算法主要是将要被修改的数据的最新记录中的DB—_TRX_ID(当前事务id)取出来,与系统当前其他活跃事务的id去对比,如果DB TRX_ID Read View的属性做了比较,不符合可见性,那么就通过DB_ROLL PTR滚指针去取出undolog中的DB_TRX_ID做比,即遍历链表中的DBTRX ID,直到找到满足条件的DB_TRX_ID,这个DB_TRX_ID所在的旧记录就是当前事务能看到的最新老版本教据

Read View的可见性规则如下所示

首先要知道Read View中的三个全局属性:

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

up_limit_id:记录trx_list列表中事务ID最小的ID 1

low_limit_id:Read View生成时刻系统尚未分配的下一个事务ID,5

1、首先比较DB_TRX_ID<up_limit _id,如果小于,则当前事务能看到DB_TRX_ID所在的记录,如果大于等于进入下一个判断

2、接下来判断DB_TRX_ID >= low limit id,如果大于等于则代表DB_TRX_ID所在的记录在Read View生成后才出现的,那么对于当事务肯定不可见,如果小于,则进入下一步判断

3,判断DB_TRX_ID是否在活跃事务中,如果在,则代表在Read View生成时刻,这个事务还是活跃状态,还没有commit,修改的数据当前事务也看不到  如果不在则说明这个事务在Read View生成之前就已经开始commit,那么修改的结果是能够看见的。

7一个案例看看MVCC流程。

从上述表格中,我们可以看到,当事务2对某行数据执行了快照读,数据库为该行数据生成一个Read View视图,可以看到事务1和事务3还在活跃状态,事务4在事务2快照读的前一刻提交了更新,所以,在Read View中记录了系统当前活跃事务1,3,维护在一个列表中。同时可以看到up limit id的值为1.而low imit id为5,如下图所示:


因为事物4>1 4<5 并且4不在活跃事务中,所以 2事务可以读到已经提交的最新值

8、RC、RR(可重复读)级别下的InnoDB快照读有什么不同

因为Read View生成时机的不同,从而造成RC、RR级别下快照读的结果的不同

1、在RR级别下的某个事务的对某条记录的第一次快照读会创建一个快照即Read View,将当前系统活跃的其他事务记录起来,此后调用决照读的时候,还是使用的是同一个Read View,所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使都是同一个Read view,所以对之后的修改不可见

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

3、在RC级别下,事务中,每次快照读都会新生成一个快照和Read View,这就是我们在RC级别下的事务中可以看到别的事务提交的新的原因。


可重复读是在事务开启之前生成Read view 视图 读已提交 是在查询的时候生成Read view视图


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
9月前
|
关系型数据库 MySQL
|
9月前
|
Oracle 关系型数据库 MySQL
MySQL相关(六)- 事务隔离级别的实现方案(MVCC)
MySQL相关(六)- 事务隔离级别的实现方案(MVCC)
102 0
|
2天前
|
SQL 关系型数据库 MySQL
京东面试:MySQL MVCC是如何实现的?如何通过MVCC实现读已提交、可重复读隔离级别的?
1.请解释什么是MVCC,它在数据库中的作用是什么? 2.在MySQL中,MVCC是如何实现的?请简述其工作原理。 3.MVCC是如何解决读-写和写-写冲突的? 4.在并发环境中,当多个事务同时读取同一行数据时,MVCC是如何保证每个事务看到的数据版本是一致的? 5.MVCC如何帮助提高数据库的并发性能?
京东面试:MySQL MVCC是如何实现的?如何通过MVCC实现读已提交、可重复读隔离级别的?
|
3月前
|
存储 关系型数据库 MySQL
MySQL MVCC全面解读:掌握并发控制的核心机制
【10月更文挑战第15天】 在数据库管理系统中,MySQL的InnoDB存储引擎采用了一种称为MVCC(Multi-Version Concurrency Control,多版本并发控制)的技术来处理事务的并发访问。MVCC不仅提高了数据库的并发性能,还保证了事务的隔离性。本文将深入探讨MySQL中的MVCC机制,为你在面试中遇到的相关问题提供全面的解答。
400 2
|
1月前
|
SQL 存储 关系型数据库
MySQL进阶突击系列(05)突击MVCC核心原理 | 左右护法ReadView视图和undoLog版本链强强联合
2024年小结:感谢阿里云开发者社区每月的分享交流活动,支持持续学习和进步。过去五个月投稿29篇,其中17篇获高分认可。本文详细介绍了MySQL InnoDB存储引擎的MVCC机制,包括数据版本链、readView视图及解决脏读、不可重复读、幻读问题的demo演示。
|
8月前
|
存储 关系型数据库 MySQL
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
|
3月前
|
存储 关系型数据库 MySQL
MySQL MVCC深度解析:掌握并发控制的艺术
【10月更文挑战第23天】 在数据库领域,MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种重要的并发控制机制,它允许多个事务并发执行而不产生冲突。MySQL作为广泛使用的数据库系统,其InnoDB存储引擎就采用了MVCC来处理事务。本文将深入探讨MySQL中的MVCC机制,帮助你在面试中自信应对相关问题。
256 3
|
5月前
|
关系型数据库 MySQL 数据库
MySQL高级篇——MVCC多版本并发控制
什么是MVCC、快照读与当前读、隐藏字段、Undo Log版本链、ReadView、举例说明、InnoDB 解决幻读问题
|
6月前
|
SQL 关系型数据库 MySQL
Mysql原理与调优-事务与MVCC
【8月更文挑战第19天】
|
7月前
|
SQL 存储 关系型数据库
(九)MySQL之MVCC机制:为什么你改了的数据我还看不见?
在《MySQL锁机制》这篇文章中,咱们全面剖析了MySQL提供的锁机制,对于并发事务通常可以通过其提供的各类锁,去确保各场景下的线程安全问题,从而能够防止脏写、脏读、不可重复读及幻读这类问题出现。
192 0