Mysql--技术文档--MVCC(Multi-Version Concurrency Control | 多版本并发控制)

MVCC到底是什么

        MVCC(Multi-Version Concurrency Control)是一种并发控制机制,用于解决并发访问数据库时的数据一致性和隔离性问题。MVCC允许多个事务同时读取数据库的同一数据,而不会相互干扰或导致冲突。

        在传统的并发控制机制中,如锁定机制,事务会对读取和写入的数据进行加锁,以确保每个事务独占所需的资源。然而,这种悲观并发控制机制可能导致资源争用和性能问题,尤其是在高并发环境下。

一文读懂数据库的MVCC实现原理

 MVCC是innodb实现事务并发与回滚的重要功能!!!!!

MVCC解决了哪些问题

MVCC(Multi-Version Concurrency Control)解决了以下几个关键问题:

  1. 读-写冲突:传统的并发控制机制,如锁定机制,可能导致读取和写入操作之间的冲突。当多个事务试图同时读取和写入相同的数据时,会发生资源争用问题。MVCC通过并发控制的方式,让读取操作不受写入操作的干扰,从而避免了这种读-写冲突。

  2. 写-写冲突:在传统的并发控制机制中,当多个事务同时试图写入相同的数据时,会发生写入冲突。这可能导致数据的不一致性以及事务的回滚和重试。MVCC通过并发控制,使得每个事务都操作自己的独立版本,从而避免了写-写冲突,提高了并发性能。

  3. 隔离性问题:在多用户并发操作中,隔离性是确保事务之间互不干扰的重要属性。传统的并发控制机制,如锁定机制,可能导致事务之间的阻塞和相互等待。MVCC通过使用多个版本和快照读取,实现了事务之间的隔离性,使得事务可以并发执行而互不干扰。

  4. 性能问题:传统的并发控制机制中,加锁的方式可能导致较高的开销和资源争用,特别是在高并发环境下。MVCC采用了乐观的并发控制方式,减少了锁冲突和资源争用,从而提高了并发性能和系统吞吐量。

综上所述,MVCC通过解决读-写冲突、写-写冲突、隔离性问题和性能问题,提供了更好的并发控制机制。它通过版本管理和快照读取,使得多个事务可以并发执行而互不干扰,从而提高了数据库的性能、可用性和一致性。

MVCC底层机制-具体实现

具体的实现是,在数据库的每一行中,添加额外的三个字段:

  1. DB_TRX_ID – 记录插入或更新该行的最后一个事务的事务 ID
  2. DB_ROLL_PTR – 指向改行对应的 undolog 的指针
  3. DB_ROW_ID – 单调递增的行 ID,他就是 AUTO_INCREMENT 的主键 ID

在MVCC的实现中,使用乐观锁和额外的字段来实现并发控制。以下是对每个字段的具体解释和MVCC如何使用乐观锁的简单概述:

  1. DB_TRX_ID(事务ID):这个字段用于记录插入或更新行的最后一个事务的事务ID。每个事务在执行写操作时,都会生成一个唯一的事务ID并关联到相关数据行。这样,MVCC可以通过比较事务ID来确定事务执行期间的数据版本。

  2. DB_ROLL_PTR(undolog指针):这个字段指向对应行的undolog的指针。undolog是InnoDB存储引擎用于实现事务的撤销(undo)或回滚(rollback)操作的日志。通过保留undolog指针,MVCC可以在事务回滚或读取旧版本数据时进行快速回溯到适当的undolog。

  3. DB_ROW_ID(行ID):这个字段是单调递增的行ID,通常用作AUTO_INCREMENT主键ID。它提供了一种方式来唯一标识每一行,以便MVCC在处理并发操作时进行准确定位。

MVCC使用乐观锁来确保对数据行的并发访问不会产生冲突。它通过比较事务的启动时间戳(或序列号)和数据行的事务ID来判断是否存在并发冲突。当一个事务启动时,会获取所有需要读取或修改的数据行的版本信息,包括DB_TRX_ID和DB_ROLL_PTR字段。在读取或修改数据时,MVCC会使用这些版本信息进行验证,以确定是否访问的是合适的数据版本。

如果在事务执行期间,发现其他事务已经修改了数据行的版本(事务ID不一致),则会回滚当前事务,因为它访问的是过期的数据版本。这种方式可以避免读-写冲突和写-写冲突,提供了一致的数据访问和更新。

需要注意的是,MVCC的具体实现可能会有一些细微的差异,因为不同的数据库管理系统可能采用不同的方式来处理并发控制。但是上述提到的字段和基本思想是MVCC的常见实现方式之一。

总而言之,MVCC使用乐观锁和额外的字段来实现并发控制。通过比较事务ID和版本信息,MVCC可以识别并处理并发访问冲突,从而确保数据的一致性和隔离性。

悲观锁和乐观锁的对比

Mysql--技术文档--悲观锁、乐观锁-《控制并发机制简单认知、深度理解》_一单成的博客-CSDN博客

MVCC实现的三大要素

使用范围:

        首先要明白mvcc只在REPEATABLE READ(可重复读) 和 READ COMMITTED(已读提交)这两个隔离级别下面使用。

REPEATABLE(可重复的)、COMMITTED(承诺)

MVCC实现原理是两个隐式字段、undo日志、Read view来实现的。

1. 隐式字段

在Innodb存储引擎中,在有聚簇索引的情况下每一行记录中都会隐藏俩个字段,如果没有聚簇索引则还有一个6byte的隐藏主键。

这俩个隐藏列一个记录的是何时被创建的,一个记录的是什么时候被删除。

这里不要理解为是记录的是时间,存储的是事务ID。

俩个隐式字段为DB_TRX_ID,DB_ROLL_PTR,没有聚簇索引还会有DB_ROW_ID这个字段。

  • DB_TRX_ID:记录创建这条数据上次修改它的事务 ID
  • DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本

        隐式字段实际还有一个delete flag字段,即记录被更新或删除,这里的删除并不代表真的删除,而是将这条记录的delete flag改为true

        MySQL提供了逻辑删除的方式,可以通过在表中添加一个额外的列(例如delete_flag字段)来实现。逻辑删除是将记录标记为已删除的状态,而不是将其物理删除。这种方式保留了记录的历史信息,并且可以根据需要恢复或审计已删除的记录。在执行查询操作时,可以使用查询条件来过滤掉已标记为删除的记录。

2. undo log(回滚日志)

之前对undo log的作用只提到了回滚操作实现原子性,现在需要知道的另一个作用就是实现MVCC多版本控制器。

undo log细分为俩种,insert时产生的undo log、update,delete时产生的undo log

在Innodb中insert产生的undo log在提交事务之后就会被删除,因为新插入的数据没有历史版本,所以无需维护undo log。

update和delete操作产生的undo log都属于一种类型,在事务回滚时需要,而且在快照读时也需要,则需要维护多个版本信息。只有在快照读和事务回滚不涉及该日志时,对应的日志才会被purge线程统一删除。

purge线程会清理undo log的历史版本,同样也会清理del flag标记的记录。

undo log在mvcc中的作用

写到这里关于undo log在mvcc中的作用估计还是蒙圈的。

undo log保存的是一个版本链,也就是使用DB_ROLL_PTR这个字段来连接的。

当数据库执行一个select语句时会产生一致性视图read view

那么这个read view是由查询时所有未提交事务ID组成的数组,数组中最小的事务ID为min_id和已创建的最大事务ID为max_id组成,查询的数据结果需要跟read-view做比较从而得到快照结果。

所以说undo log在mvcc中的作用就是为了根据存储的事务ID和一致性视图做对比,从而得到快照结果。

3、undo log底层实现

在原始数据执行一条语句之后将undo log记录发生变化。

也就是说在一条语句更新的时候会把原有的数据拷贝到undo log日志中。

然后使用指针在最新的记录和旧的记录连接一条线,也就是存放undo log日志的指针地址。

最后需要的时候通过指针来找到历史数据。

Undo Log(回滚日志)是用于实现事务的原子性和一致性的一个重要组成部分。它是在事务执行期间记录数据修改操作的地方,并可用于回滚事务或恢复数据到之前的状态。

Undo Log的底层实现是通过使用一种称为"回滚段"的数据结构。回滚段是专门用于存储Undo Log的数据结构,它位于表空间中的一个特殊位置。

每个事务在执行修改操作前,会在Undo Log中为所涉及的数据行生成一个“回滚记录”。这个回滚记录存储了修改前的数据值(原始数据值),以及用于回滚操作的其他相关信息。

当事务需要回滚时,Undo Log可以通过相反的操作撤消该事务的修改。它会使用回滚记录中的原始数据值来将数据恢复到事务开始之前的状态。

此外,Undo Log还用于处理并发事务之间的读取一致性。在MVCC中,读取操作需要使用Undo Log来判断某个数据版本是否对当前事务可见。

总的来说,Undo Log的底层实现基于回滚段数据结构,它在事务执行期间记录数据的修改操作,并在事务回滚或 MVCC 快照读取时使用这些信息。这个机制确保了事务的原子性、一致性和隔离性,并为数据库提供了数据恢复和读取一致性的支持。

4、read-view

MySQL中的read-view(读视图)。在MySQL中,视图是一种虚拟表,它是根据一个或多个表的查询结果创建的。视图可以被看作是存储在数据库中的虚拟表格,可以像表一样查询和使用。

使用read-view可以实现以下功能:

  • 简化复杂的查询:通过创建视图,你可以将复杂的查询逻辑封装到一个简单的视图中,然后在查询中使用该视图,从而简化查询语句。

  • 访问权限控制:通过使用视图,你可以只向用户展示需要的数据,而隐藏底层表的细节。这提供了更好的安全性和数据访问控制。

  • 数据的逻辑组织:通过创建视图,你可以根据业务需求将表的数据进行组织和过滤,从而更好地管理和理解数据。

总之,read-view(读视图)是在MySQL中创建的一种虚拟表,可以用于简化查询、控制数据访问权限以及逻辑组织数据。

当执行SQL语句查询时会产生一致性视图,也就是read-view,它是由查询的那一时间所有未提交事务ID组成的数组,和已经创建的最大事务ID组成的。

在这个数组中最小的事务ID被称之为min_id,最大事务ID被称之为max_id,查询的数据结果要根据read-view做对比从而得到快照结果。

阿丹理解:

        这个概念其实就是在mysql中mvcc中的类似于快照的概念,因为innodb不是使用的是mvcc+乐观锁来解决并发问题嘛,对于操作进行锁不对读来锁,然后在进行操作的时候去对比之前的改之前的版本的。

        这个概念对于mvcc的作用是在一个事务开始时,它会根据自己的Read-View创建一个快照,并在整个事务期间使用这个快照进行读取操作。这个快照包含了事务开始时数据库的一个一致视图。

5、版本链对比规则

MVCC在MySQL中的实现底层包括以下几个组成部分:

  1. 版本链:每个数据行都有一个版本链,用于存储该数据行的多个版本。版本链可以是链表或者树形结构,具体的实现取决于MySQL的版本和存储引擎。版本链中的每个版本都包含了数据的实际内容以及相关的时间戳信息。

  2. 事务的时间戳:每个事务在开始时都会被分配一个时间戳。事务的时间戳用于判断每个版本对于该事务的可见性。

  3. 数据行的锁:为了保证并发事务的一致性,MySQL使用了锁机制。在MVCC中,数据行的读锁会阻止写事务对该数据行的修改操作,而写锁会阻止其他事务对该数据行的读写操作。

  4. 读取操作的一致性视图:每个事务在执行读取操作时会创建一个一致性视图。该一致性视图会基于事务的时间戳和数据行版本的时间戳来确定每个数据行对于该事务的可见性。

不同的存储引擎在MVCC的实现上可能会有细微的差异,因为存储引擎负责管理数据的存储和访问。例如,InnoDB存储引擎使用了undo日志和read-view机制来实现MVCC,而MyISAM存储引擎则没有内置的MVCC实现。

如果落在trx_id<min_id,表示此版本是已经提交的事务生成的,由于事务已经提交所以数据是可见的

如果落在trx_id>max_id,表示此版本是由将来启动的事务生成的,是肯定不可见的

若在min_id<=trx_id<=max_id时

  • 如果row的trx_id在数组中,表示此版本是由还没提交的事务生成的,不可见,但是当前自己的事务是可见的
  • 如果row的trx_id不在数组中,表明是提交的事务生成了该版本,可见

在这里还有一个特殊情况那就是对于已经删除的数据,在之前的undo log日志讲述时说了update和delete是同一种类型的undo log,同样也可以认为delete就是update的特殊情况。

当删除一条数据时会将版本链上最新的数据复制一份,然后将trx_id修改为删除时的trx_id,同时在该记录的头信息中存在一个delete flag标记,将这个标记写上true,用来表示当前记录已经删除。

在查询时按照版本链的规则查询到对应的记录,如果delete flag标记位为true,意味着数据已经被删除,则不返回数据。

 trx_id:

代表事务ID,用于标识每个事务的唯一性。它可以用于确定事务的开始时间和提交时间。

min_id:

最小可见事务ID。它表示正在执行的事务所能看到的最早提交的事务的ID。事务ID小于"min_id"的所有事务都是已经提交的事务,对于当前事务而言,它们的修改是可见的。

总结:

"trx_id"和"min_id"是MVCC中用于判断数据对于当前事务的可见性的重要标识。

注意:

对于已经删除的数据,在MVCC中会将最新版本的数据进行复制,并将"trx_id"修改为删除时的"trx_id"。同时,在记录的头信息中设置一个"delete flag"标记来表示该记录已经被删除。当查询时根据版本链的规则进行查询,如果"delete flag"标记为true,表示该数据已经被删除,因此不返回数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/110855.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

远程教育:别催了,在线巡课真爽啊

随着远程教育和在线学习的兴起&#xff0c;教学活动的场景正逐渐从传统的实体教室转向虚拟的线上平台&#xff0c;这也催生了对教学质量监管的新需求。 在线巡课系统在这一背景下应运而生&#xff0c;它不仅能够实时观察教师的教学过程&#xff0c;还能够量化评估教学效果&…

Element——table排序,上移下移功能。及按钮上一条下一条功能

需求&#xff1a;table排序&#xff0c;可操作排序上移下移功能。判断第一行上移禁用和最后一行下移禁用&#xff0c;排序根据后端返回的字段 <el-table:data"tableData"style"width: 100%"><el-table-column type"index" label"序…

先进API生产力工具eqable HTTP,一站式开发调试工具推荐

简介 Reqable是什么? Regable Fiddler/Charles Postman Reqable是HTTP一站式开发调试国产化解决方案&#xff0c;拥有更便捷的体验&#xff0c;更先进的协议&#xff0c;更高效的性能和更精致的界面。 Reqable是一款跨平台的专业HTTP开发和调试工具&#xff0c;在全平台支持…

APSIM模型应用与参数优化、批量模拟

APSIM (Agricultural Production Systems sIMulator)模型是世界知名的作物生长模拟模型之一。APSIM模型有Classic和Next Generation两个系列模型&#xff0c;能模拟几十种农作物、牧草和树木的土壤-植物-大气过程&#xff0c;被广泛应用于精细农业、水肥管理、气候变化、粮食安…

ElasticSearch总结

ES是什么 ES是一个天生支持分布式的搜索、聚合分析的存储引擎 基于Java开发 基于Lucene的开源分布式搜索引擎 ELK &#xff1a; elasticSearch Logstah Kibana 加入 Beats 后 ELK 改为 &#xff1a;Elastic stack ES解决了什么问题 ES解决的核心问题 &#xff1a; 1.海量数…

Vue2向Vue3过度核心技术工程化开发和脚手架

目录 1 工程化开发和脚手架1.1 开发Vue的两种方式1.2.脚手架Vue CLI 2 项目目录介绍和运行流程2.1 项目目录介绍2.2 运行流程 3 组件化开发4 根组件 App.vue4.1 根组件介绍4.2 组件是由三部分构成4.3 总结 5 普通组件的注册使用-局部注册5.1 特点&#xff1a;5.2 步骤&#xff…

爬虫异常处理之如何处理连接丢失和数据存储异常

在爬虫开发过程中&#xff0c;我们可能会遇到各种异常情况&#xff0c;如连接丢失、数据存储异常等。本文将介绍如何处理这些异常&#xff0c;并提供具体的解决代码。我们将以Python语言为例&#xff0c;使用requests库进行网络请求和sqlite3库进行数据存储。 1. 处理连接丢失 …

GD32-舵机的原理

GD32-舵机的原理 舵机的现一脉宽与舵机转动角度 旋转编码器的原理 顺时针&#xff1a;A的下降沿时&#xff0c;B处于高电平&#xff1b; 逆时针&#xff1a;A的下降沿时&#xff0c;B处于低电平&#xff1b; #ifndef _ENCODER_DRIVE_H #define _ENCODER_DRIVE_H#include &quo…

开源软件的崛起:历史与未来

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

5.Redis-string

string 字符串 字符串类型是 Redis 最基础的数据类型&#xff0c;关于字符串需要特别注意&#xff1a; 1.⾸先Redis中所有 key 的类型都是字符串类型&#xff0c;⽽且其他⼏种数据结构也都是在字符串类似基础上构建的&#xff0c;例如 list 和 set 的元素类型是字符串类型。 2…

每日一题 823. 带因子的二叉树

每日一题 823. 带因子的二叉树 难度&#xff1a;中等 思路&#xff1a; 取乘积&#xff0c;那么两个叶子节点相乘一定会得到一个更大的数&#xff0c;所以先排序以父节点为根节点的数的数量 以右节点为根节点的数的数量 * 以左节点为根节点的数的数量初始化列表&#xff0c;…

花5分钟判断,你的Jmeter技能是大佬还是小白!

jmeter 这个工具既可以做接口的功能测试&#xff0c;也可以做自动化测试&#xff0c;还可以做性能测试&#xff0c;其主要用途就是用于性能测试。但是&#xff0c;有些公司和个人&#xff0c;就想用 jmeter 来做接口自动化测试。 你有没有想过呢&#xff1f; 下面我就给大家讲…

多线程(二)

一.关于线程的常用操作 1.启动线程 run(): 对于run方法的覆写只是指定线程要做的任务清单&#xff0c;而不是真正的启动线程 start()&#xff1a; start()方法才是真正的在底层创建出一个线程&#xff0c;并且启动 2.中断线程 1.通过共享的标记来中断 package demo; impor…

unity-AI自动导航

unity-AI自动导航 给人物导航 一.地形创建 1.首先我们在Hierarchy面板中创建一个地形对象terrian&#xff0c;自行设定地形外貌&#xff0c;此时我们设置一个如下的地形外观。 二.创建导航系统 1.在主人公的Inspector、面板中添加Nav Mesh Agent &#xff08;导航网格代理&…

python中的matplotlib画直方图(数据分析与可视化)

python中的matplotlib画直方图&#xff08;数据分析与可视化&#xff09; import numpy as np import pandas as pd import matplotlib.pyplot as pltpd.set_option("max_columns",None) plt.rcParams[font.sans-serif][SimHei] plt.rcParams[axes.unicode_minus]Fa…

【Linux】进程通信 — 信号(下篇)

文章目录 &#x1f4d6; 前言1. 阻塞信号1.1 信号其他相关常见概念&#xff1a;1.2 sigset_t&#xff1a;1.2 - 1 信号集操作函数 1.3 sigprocmask&#xff1a;1.4 sigpending&#xff1a; 2. 进程处理信号2.1 内核页表和用户页表&#xff1a;2.2 内核态和用户态&#xff1a;2.…

「Vue|网页开发|前端开发」02 从单页面到多页面网站:使用路由实现网站多个页面的展示和跳转

本文主要介绍如何使用路由控制来实现将一个单页面网站扩展成多页面网站&#xff0c;包括页面扩展的逻辑&#xff0c;vue的官方路由vue-router的基本用法以及扩展用法 文章目录 本系列前文传送门一、场景说明二、基本的页面扩展页面扩展是在扩什么创建新页面的代码&#xff0c;…

面试题-React(七):React组件通信

在React开发中&#xff0c;组件通信是一个核心概念&#xff0c;它使得不同组件能够协同工作&#xff0c;实现更复杂的交互和数据传递。常见的组件通信方式&#xff1a;父传子和子传父 一、父传子通信方式 父组件向子组件传递数据是React中最常见的一种通信方式。这种方式适用…

SpringBoot异步方法支持注解@Async应用

SpringBoot异步方法支持注解Async应用 1.为什么需要异步方法&#xff1f; 合理使用异步方法可以有效的提高执行效率 同步执行(同在一个线程中): 异步执行(开启额外线程来执行): 2.SpringBoot中的异步方法支持 在SpringBoot中并不需要我们自己去创建维护线程或者线程池来…

C#_进程单例模式.秒懂Mutex

什么是Mutex? 可以定义调用线程是否具有互斥性&#xff0c;程序创建者拥有控制权&#xff0c;相反只能引用程序。 参数1&#xff1a;如果是程序创建者&#xff0c;就获得控制权。 参数2&#xff1a;名称&#xff0c;可使用GUID生成。 参数3&#xff1a;out 返回值&#xf…