当前位置: 首页 > news >正文

mysql的mvcc详解

一 MVCC的作用

1.1 mvcc的作用

1.MVCC(Multiversion Concurrency Control)多版本并发控制。即通过数据行的多个版本管理来实现数据库的并发控制,使得在InnoDB事务隔离级别下执行一致性读操作有了保障。

2.mysql中的InnoDB中实现了MVCC主要是为了提高数据库的并发性能,在无锁的情况下也能处理读写并发,大大提高数据库的并发度。

3..MySQl中只有InnoDB支持MVCC,其他存储引擎不支持

4.为了查询一些正在被其他事务更新的值的时候,能够查到它们被更新之前的值,这样做就能在查询的时候不必等待更新事务的提交。

在InnoDB中,会对增删改操作自动添加排它锁,因此两个事务不会出现脏写的情况,也就是不会出现两个事务交叉着对同一条记录进行修改,必须等待第一个事务提交才能进行第二个事务。

1.2 快照读与当前读的区别与联系

1.MVCC在InnoDB中的实现主要是为了提高数据库的并发性能,用更好的方式处理读写冲突,做到即使有读写冲突,也能不加锁实现非堵塞并发读,这个读指的是快照读而不是当前读。

2.当前读实质上是一种加锁的操作,是悲观锁的体现;而MVCC是采用乐观锁的一种方式

1.3 快照读

1.快照读,顾名思义读取的是一份快照数据,所以读到的并不一定是最新数据,可能是历史数据。

2.简单的select查询就是快照读,不加锁非阻塞读,降低数据库的开销。

3.但是快照读在隔离级别是串行化级别是没有意义的,因为串行化的sql都是排队执行的,不存在并发,所以就会变成当前读。

1.4 当前读

当前读获取的数据是最新数据,而且在读取时不能被其他修改的,所以会对读取的记录加锁来控制。

加锁的SELECT(共享或排它锁)或者对数据进行增删改操作(自动添加排它锁)都会进行当前读。

select * from ajisun where id > 1 lock in share mode;// 或者select * from ajisun where id >1 for update;

1.5 mvcc可以解决问题

  1. 读写之间的堵塞问题,提高事务的并发读写能力

  2. 降低了死锁的概率,MVCC采用了乐观锁的方式,读取数据的时候不需要加锁,对于写操作,也只要锁定必要的行

  3. 解决快照读问题,当查询数据库某个时间节点的快照的时候,只能查看到在这个节点之前提交的事务的结果而看不到时间点之后事务提交的更新结果

1.6 mvcc面试题:mvcc是怎么实现的

mvcc 是多版本并发控制,通过生成记录的历史版本解决幻读问题,并提高数据库的性能,无锁实现读写并发操作。

1.mvcc 的实现主要是通过三个隐藏字段,undo log以及readView 实现的。

2.三个隐藏字段分别是隐藏主键,事务ID,回滚指针。

3.undo log是各个事务修改同一条记录的时候生成的历史记录,方便回滚,同时会生成一条版本链。

4.readView是事务在进行快照读的时候生成的记录快照,用于判断数据的可见性。

5.描述readView 可见性判断规则。

二  MVCC实现原理

2.1 原理

​ MVCC的实现依赖于:隐藏字段Undo logRead View 

2.2 undo log

2.2.1 undo Log的作用

所谓的版本链就是在MVCC中,多个事务对同一行记录进行更新会产生多个历史快照,这些记录保存在Undo Log里,这些undo日志通过回滚指针串联在一起。

undo log就是回滚日志,在insert/update/delete变更操作的时候生成的记录方便回滚。

当进行insert操作的时候,产生的undo log只有在事务回滚的时候需要,如果不回滚在事务提交之后就会被删除。

当进行update和delete的时候,产生的undo log不仅仅在事务回滚的时候需要,在快照读的时候也是需要的,所以不会立即删除,只有等不再用到这个日志的时候才会被mysql purge线程统一处理掉(delete操作也只是打一个删除标记,并不是真正的删除)。

2.2.2 undo Log的组成

​ undo log的版本链,对于使用InnoDB存储引擎的表来说,它的聚簇记录中包含两个必要的索引列:

1.trx_id:每次事务对聚簇记录进行修改的时候,就会将该事务的id复制给trx_id隐藏列

2.roll_pointer:每次对每条聚簇索引进行改动的时候,都会将旧的版本信息写入undo log中,通过回滚指针就能找到记录修改前的信息。

2.2.3 undo Log的案例

1.假设两个事务id分别为10、20的事务分别对这条记录进行Update操作。

2.每次对记录进行改动,都会记录一条undo log,每个undo log都包含创建它的事务id,每条undo log都会有一个roll pointerINSERT操作不会有,因为插入没有更新的版本),这些undo log通过roll pointer连接起来,串成一个链表,这个链表就成为undo log 版本链。

3.如下图:

2.3 隐藏字段

除了我们正常业务涉及的字段外,InnoDB在内部向数据库表中添加三个隐藏字段:

1.DB_TRX_ID:6-byte的事务ID。插入或更新行的最后一个事务的事务ID

2.DB_ROLL_PTR:7-byte的回滚指针。就是指向对应某行记录的上一个版本,在undo log中使用。

3.DB_ROW_ID:6-byte的隐藏主键。如果数据表中没有主键,那么InnoDB会自动生成单调递增的隐藏主键(表中有主键或者非NULL的UNIQUE键时都不会包含 DB_ROW_ID列)。

如上面的表没有设计primary key,其中id/name/city是我们的业务字段,那么加上隐藏字段应该如下

 

2.4  ReadView

2.4.1 ReadView的作用

ReadView 是事务快照读的时候产生的数据读视图,在该事务执行快照读的那一刻,会生成一个数据系统当前的快照,记录并维护系统当前活跃事务的id,事务的id值是递增的。

Read View就是事务在使用MVCC机制在进行快照读操作时产生的快照,ReadView 的最大作用就是判断数据的可见性,当某个事务执行快照读的时候,会对此记录创建一个ReadView 的视图,在整个事务期间根据某些条件判断该事务能够看到的版本链上的哪条历史数据。

2.4.2  ReadView的组成

  1. creator_id:创建这个Read View的事务id

  2. trx_ids:表示创建这个Read View的时候正在活跃的事务id列表

  3. up_limit_id:活跃的事务中最小的id

  4. low_limit_id:表示生成low_limit_id时系统应该分配给下一个事务的id值,low_limit_id是系统最大的事务id(而不是活跃的最大事务id)

***low_limit_id并不是trx_ids的最大值而是系统能够分配的事务id最大值,事务id是递增分配的,并且只有事务在进行增删改操作的时候才会分配事务ID。比如现在有1 2 5三个事务,那么id为5的事务提交后,一个新事务在生成ReadView的时候,trx_ids就包括1 2,up_limit_id就是1,low_limit_id就是6

此时如果有事务创建Read View,则

  • trx_ids=[trx2, trx3, trx5, trx8]
  • up_limit_id=trx2
  • low_limit_id=trx8+1

2.4.3  ReadView的判断流程

当查询一条数据的时候,系统

  1. 首先获取查询操作的事务的版本号
  2. 获取当前系统的ReadView
  3. 将查询到的数据与ReadView中的事务版本号进行比较
  4. 如果不符合ReadView的规则,则通过回滚指针形成的Undo Log版本链undo log中获取符合规则的历史快照
  5. 返回符合规则的数据

快照记录创建这个Read View的事务id、活跃的事务中最小的id、系统最大的事务id,并且InnoDB会为每个事务构建了一个数组,用来记录并维护系统当前活跃事务的ID(活跃指的是启动了还没有提交),等到访问某条记录的时候,就可以根据上面记录的内容判断记录版本对当前事务可不可见

1.如果Read Viewcreator_id当前事务的id相同,则意味着当前事务在访问它修改过的id,所以该记录版本可以被事务访问

2.如果当前访问版本记录的trx_id小于Read Viewup_limit_id,则意味着修改该数据版本的事务已经提交,所以该版本的记录可以被当前事务访问

3.如果当前访问版本记录的trx_id大于等于Read Viewlow_limit_id,则意味着创建该数据版本的事务是在ReadView生成之后才出现的,因此当前事务不能访问

4.如果当前访问版本记录的trx_idRead Viewup_limit_idlow_limit_id之间,则需要判断trx_id是否在Read Viewtrx_ids活跃事务列表中,如果在则说明事务还没有提交当前事务不能访问,否则可以访问

5.如果某个版本对当前事务不可见,那么顺着版本链找到下个版本记录,然后继续上面的对比规则,直到找到版本链中的最后一个版本,如果最后一个版本都不可见,那么该条记录对此事务完全不可见,也就查不到这个记录。

2.5 不同隔离级别使用Readview

1.读未提交:能够读取未提交的事务修改的数据,所以直接读取最新的记录就可以,不必使用MVCC

2.读已提交:不能读取未提交的事务修改的数据,并且不能进行重复读取,事务中,每次快照读都会新生成一个快照和ReadView,这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因。

3.可重复读:不能读取未提交的事务修改的数据,并且能进行重复读取,所以只在第一次查询的时候获取一次ReadView,之后查询都只查看已经生成的ReadView副本

4.可串行化:InnoDB规定使用加锁的方式来访问记录,通过加锁的方式让所有sql都串行化执行了,也是读最新的,不存在快照读ReadView。

https://www.cnblogs.com/tod4/p/17384677.html

MySQL进阶系列:多版本并发控制mvcc的实现

2.6  mvcc解决幻读问题

MySQL在Repeatable Read隔离级别下是可以解决幻读问题的,解决的方案有两种:

1.使用MVCC进行快照读,写使用临键锁。添加的临键锁不会影响快照读,只会影响到想要获取锁的读操作

2.读写加锁,也就是使用可串行化的隔离模式。

2.6.1 mvcc解决幻读

读操作利用多版本并发控制MVCC),写操作加锁。

MVCC就是生成一个ReadView,通过ReadView能够找到符合条件的记录版本(历史版本由undo log提供查询),查询语句执行查询已经提交的事务做出的更改,对于没由提交的事务和ReadView创建之后的事务做出的更改是看不到的。而写操作肯定是针对的最新版本的记录,因此读记录的历史版本和写操作的最新记录版本并不会冲突,也就是采用MVCC时,读写操作并不会冲突。

普通的SELECT语句在READ COMMITTED 和 REPEATABLE READ隔离级别下的读操作就是利用MVCC进行的读

1.READ COMMITTED:由于不会读取没有提交的事务修改的数据版本,因此避免了脏读问题

2.REPEATABLE READ:由于不会读取Read View创建之后的事务更改的数据(一个事务只有在第一次执行SELECT语句才会生成一个Read View,之后的SELECT语句都在复用),因此避免了可重复读和幻读问题。

2.6.2 通过加锁的方式

读、写操作都采用加锁的方式

在一些业务场景中,不允许读取数据的历史版本,即每次都需要去读取磁盘中最新的数据,这样也就意味着读操作也需要和写操作一样排队执行。

如此一来,脏读不可重复读问题都得到了解决,因为读操作和写操作的串行执行,不会出现一个事务读取另一个未提交事务的数据以及一个事务读取过程中另一个事务修改数据提交导致前一个事务前后读取数据不一致的情况(第二个事务根本无法开始)

****但是,幻读问题有些尴尬,试想一个事务在进行读操作,因此给表中的一定范围内的数据加锁,但是另一个事务要写的这个幻影数据可不在这个范围里面,也就是两个读写操作并不会冲突,仍然会出现幻读问题解决这一个问题的办法就是写操作使用临键锁

相关文章:

mysql的mvcc详解

一 MVCC的作用 1.1 mvcc的作用 1.MVCC(Multiversion Concurrency Control)多版本并发控制。即通过数据行的多个版本管理来实现数据库的并发控制,使得在InnoDB事务隔离级别下执行一致性读操作有了保障。 2.mysql中的InnoDB中实现了MVCC主要…...

FreeRTOS两个死机原因(中断调用接口异常)【杂记】

1、中断回调函数中没有使用中断级API (xxFromISR) 函数 xSemaphoreGiveFromISR(uart_busy,&HighterTask);----正确 xSemaphoreGive(uart_busy);-----错误2、比configMAX_SYSCALL_INTERRUPT_PRIORITY优先级高的中断函数中使用了FreeRTOS的函数 3、临界代码保护后不可调用os…...

【AI视野·今日Robot 机器人论文速览 第四十三期】Thu, 28 Sep 2023

AI视野今日CS.Robotics 机器人学论文速览 Thu, 28 Sep 2023 Totally 37 papers 👉上期速览✈更多精彩请移步主页 Interesting: 📚****触觉力控学习策略,基于触觉的主动推理与力控用于小孔插入任务。提出了姿态控制与插入控制双策略模型。 (from 东京大学…...

批量快捷创建新数组的几种方式

1. for循环, push(比较简单, 就不上代码了) 2.创建空数组,填充null,然后map: function createData() { return new Array(1000) .fill(null) .map((v,i)>({name: name${i1}})) } console.log(createData()) 3.Array.frommap function createData() { return Array.from…...

单目标应用:基于沙丁鱼优化算法(Sardine optimization algorithm,SOA)的微电网优化调度MATLAB

一、沙丁鱼优化算法 沙丁鱼优化算法(Sardine optimization algorithm,SOA)由Zhang HongGuang等人于2023年提出,该算法模拟沙丁鱼的生存策略,具有搜索能力强,求解精度高等特点。 沙丁鱼主要以浮游生物为食,这些生物包括细菌、腔肠…...

基于Halo搭建个人博客

准备 云服务器 安装Docker 开启8090端口 步骤 拉取Halo镜像 docker pull halohub/halo:2.1.0 制作容器并启动 docker run -it -d --name halo -p 8090:8090 -v ~/.halo2:/root/.halo2 halohub/halo:2.1.0 --halo.external-urlhttp://服务器ip:8090/ --halo.security.in…...

DPDK系列之三十一DPDK的并行机制简介

一、并行机制 什么是并行机制?这个很多开发者的眼中,其实是模糊的。可能说起来头头是道,但是细一查究竟,发现都是飘在空中的东西。在前面的“多核和多CPU编程”中,对并行机制已经进行了较深入的分析,这里只…...

【Java】复制数组的四种方式

1. System.arraycopy() 用来将一个数组的(一部分)内容复制到另一个数组里面去。 定义: void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);例: int[] arr1 { 1, 2, 3, 4, 5 }; int[] arr2 new…...

设计模式5、原型模式 Prototype

解释说明:使用原型实例指定待创建对象的类型,并且通过复制这个原型阿里创建型的对象 UML 结构图: 抽象原型(Prototype):规定了具体原型对象必须实现的clone()方法 具体原型(ConcretePrototype&…...

驱动挂载物理页代码示例

驱动挂载物理页代码示例 使用的实验环境为32位xp系统在101012分页模式下 此实验用于测试对分页模式的掌握程度 代码思路如下: 获取目标进程的cr3在目标进程中申请新的物理页拆分新申请的物理页的线性地址通过差分出的内容获取pte将pte写入到要挂载的线性地址的p…...

【新版】系统架构设计师 - 层次式架构设计理论与实践

个人总结,仅供参考,欢迎加好友一起讨论 文章目录 架构 - 层次式架构设计理论与实践考点摘要层次式体系结构概述表现层框架设计MVC模式MVP模式MVVM模式使用XML设计表现层表现层中UIP设计思想 中间层架构设计业务逻辑层工作流设计业务逻辑层设计 数据访问层…...

大数据Flink(九十):Lookup Join(维表 Join)

文章目录 Lookup Join(维表 Join) Lookup Join(维表 Join) Lookup Join 定义(支持 Batch\Streaming):Lookup Join 其实就是维表 Join,比如拿离线数仓来说,常常会有用户画像,设备画像等数据,而对应到实时数仓场景中,这种实时获取外部缓存的 Join 就叫做维表 Join。…...

Docker方式创建MySQL8的MGR集群

目录 一、MGR简述二、安装环境及要求2.1 系统版本2.2 网络要求 三、安装步骤3.1 创建容器3.2 创建用户3.3 安装插件3. 4 启动集群3.5 加入集群 四、查看集群查看 MGR 组成员列表查看 MGR 组成员拓扑信息 五、其他说明集群配置要求集群配置限制集群相关变量和状态 一、MGR简述 …...

问 ChatGPT 关于GPT的事情:扩展篇

一、GPT预训练有什么节省显存和算力的技巧吗?我如何拿四块A100完成175B模型的预训练? 对于GPT预训练,有一些技巧可以帮助节省显存和算力。以下是一些常用的技巧: 按批次截断:在较长的文本序列中,将其切割…...

Spring Boot 集成 MinIO 实现文件上传、下载和删除

MinIO 是一种开源的对象存储服务,它基于云原生架构构建,并提供了高性能、易于扩展和安全的存储解决方案。 一.安装和配置 MinIO 服务器 为了演示方便,本文采用Windows安装 1.在官方网站下载MinIO 安装文件,地址:ht…...

Polygon Miden交易模型:Actor模式 + ZKP => 并行 + 隐私

1. 引言 前序博客: Polygon Miden:扩展以太坊功能集的ZK-optimized rollupPolygon Miden zkRollup中的UTXO账户混合状态模型 Polygon Miden为: ZK-optimized rollup由客户端生成证明完善Polygon ZK系列解决方案,致力于成为网络…...

Java流的体系结构(二)

文章目录 一、对象流的使用1.概念2.序列化机制3.代码案例:序列化过程:将内存中的java对象保存到磁盘中或通过通络传输出去4.反序列化,将磁盘文件中的对象还原为内存中的一个java对象 二、RandomAccessFile的使用1.说明2.代码案例 提示&#x…...

python计算阶层

阶层(Factorial)是指从1到一个正整数n的所有整数相乘,即n! 1 2 3 … n。下面是Python代码计算阶层: def factorial(n):"""计算阶层:param n: 正整数:return: n的阶层"""if n 1 or n 0:retu…...

前端架构师之01_ES6_基础

1 初识ES6 简单来说,ECMAScript是JavaScript语言的国际标准,JavaScript是实现ECMAScript标准的脚本语言。 2011年,ECMA国际标准化组织在发布ECMAScript 5.1版本之后,就开始着手制定第6版规范。 存在的问题:这个版本…...

银行卡号识别

# 导入工具包 from imutils import contours import numpy as np import argparse import cv2 import myutils# 设置参数 # ap = argparse.ArgumentParser() # ap.add_argument("-i", "--image", required=True, # help="path to input image")…...

【Idea】idea、datagrip设置输入法

https://github.com/RikudouPatrickstar/JetBrainsRuntime-for-Linux-x64/releases/tag/jbr-release-17.0.6b829.5https://github.com/RikudouPatrickstar/JetBrainsRuntime-for-Linux-x64/releases/tag/jbr-release-17.0.6b829.5 下载后解压并重命名为 jbr, 然后替换对应 ide…...

回归预测 | MATLAB实现基于RF-Adaboost随机森林结合AdaBoost多输入单输出回归预测

回归预测 | MATLAB实现基于RF-Adaboost随机森林结合AdaBoost多输入单输出回归预测 目录 回归预测 | MATLAB实现基于RF-Adaboost随机森林结合AdaBoost多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于RF-Adaboost随机森林结合…...

最小生成树 | 市政道路拓宽预算的优化 (Minimum Spanning Tree)

任务描述: 市政投资拓宽市区道路,本着执政为民,节省纳税人钱的目的,论证是否有必要对每一条路都施工拓宽? 这是一个连问带答的好问题。项目制学习可以上下半场,上半场头脑风暴节省投资的所有可行的思路&a…...

Java实现使用多线程,实现复制文件到另一个目录,起不一样的名字,创建100万个数据

目录 1 需求2 实现 1 需求 我现在有一个300MB 的文件,想要根据这个文件,创建100万个大小一样的,名称不一样,如何实现,如何比较快点实现 2 实现 1 先准备好这个文件 2 准备好目录 3 写代码 private static void crea…...

uni-app:canvas-图形实现1

效果 代码 <template><view><!-- 创建了一个宽度为300像素&#xff0c;高度为200像素的canvas元素。canvas-id属性被设置为"firstCanvas"&#xff0c;可以用来在JavaScript中获取该canvas元素的上下文对象。 --><canvas style"width:200p…...

【算法分析与设计】动态规划(下)

目录 一、最长公共子序列1.1 最长公共子序列的结构1.2 子问题的递归结构1.3 计算最优值1.4 举例说明1.5 算法的改进 二、最大子段和2.1 代码2.2 最大子段和问题的分治算法2.3 代码2.4 分治算法的时间复杂度2.5 最大子段和问题的动态规划算法 三、凸多边形最优三角剖分3.1 三角剖…...

计算机图像处理-均值滤波

均值滤波 线性滤波器的原始数据与滤波结果是一种算术运算&#xff0c;即用加减乘除等运算实现&#xff0c;如均值滤波器&#xff08;模板内像素灰度值的平均值&#xff09;、高斯滤波器&#xff08;高斯加权平均值&#xff09;等。由于线性滤波器是算术运算&#xff0c;有固定…...

FreeRTOS入门教程(空闲任务和钩子函数及任务调度算法)

文章目录 前言一、空闲任务概念二、钩子函数概念三、任务调度算法四、任务调度算法实验1.实验代码2.是否抢占3.时间片是否轮转4.空闲任务让步 总结 前言 本篇文章将带大家学习一下什么是空闲任务以及钩子函数&#xff0c;以及学习FreeRTOS中的任务调度算法&#xff0c;了解在F…...

Javascript真的是10天内做出来的吗?

我曾听说&#xff0c;Javascript 之所以有这么多缺点&#xff0c;是因为它的第一个版本是在短短十天内完成的。我很好奇&#xff1a;1&#xff09;这是否属实&#xff1b;2&#xff09;这是否能解释这种语言的缺陷。 经过一番研究&#xff0c;我可以不自信地说&#xff1a;是的…...

picoctf_2018_got_shell

picoctf_2018_got_shell Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)32位&#xff0c;只开了NX int __cdecl __noreturn main(int argc, const char **argv, const char **envp) {_DWOR…...

物流管理网站建设/新乡网站优化公司价格

1&#xff0c;Win7 ping 不存在的地址&#xff08;请求超时&#xff09; ip routing和no ip routing no ip routing----不查路由表不配置网关---arp-catch中存在很多条目&#xff08;相当于static指出接口&#xff09;配置网关--则会arp网关一次&#xff0c;有一个条目因为路由…...

做飞机票的图片的网站/打广告去哪个平台免费

shader 试运行在可编程gpu内的小程序 使用shader开始要使用两个着色器 从vertex到fragment vertex 输入的是顶点信息&#xff0c;在中间传递最后在fragment输出color 在新的version中&#xff0c;也可以使用两者中间的 geometry shader. The geometry shader can receive primi…...

wordpress文件管理器/seo怎么发外链的

前言&#xff1a;你对手机存储到底了解多少&#xff1f;从安卓4.4以后在外置内存卡中有没有存储过东西。先上两张图片。第一张图片是酷我音乐下载设置的选项&#xff1a;酷我下载截图第二张是网易云音乐下载设置的选项&#xff1a;网易云下载截图从上面两张图可以看到外置卡的名…...

天津电商网站建设/市场营销网络

在此示例中&#xff0c;您可以获取网页上所有出现的电子邮件地址。 如果您必须更改站点的特定页面或子部分的电子邮件地址&#xff0c;则很有用。 也可能对从网页上筛选爬网电子邮件地址有用&#xff0c;尽管这不是我在这里要实现的目标。 查看更多jQuery .each示例 。 i 不敏感…...

使用net域名的大网站/百度关键词搜索排行榜

1. static全局便娘与普通全局变量有什么区别&#xff1f;static局部变量和普通局部变量有什么区别&#xff1f;satic函数与普通函数有什么区别?static全局变量只初使化一次&#xff0c;防止在其他文件单元中被引用(修改链接属性);static局部变量只被初始化一次&#xff0c;下一…...

杭州网站建设开发有限公司/搜索引擎是网站吗

参考http://www.cnblogs.com/showson/p/5602460.html 一样的解法&#xff0c;注意到在后面添加/删除与树形结构的互相转换。 【code】 http://uoj.ac/submission/77367转载于:https://www.cnblogs.com/showson/p/5602502.html...