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

MySQL事务MVCC详解

一、概述

MVCC (MultiVersion Concurrency Control) 叫做多版本并发控制机制。主要是通过数据多版本来实现读-写分离,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读,从而提高数据库并发性能。

MVCC只在已提交读(Read Committed)和可重复读(Repeatable Read)两个隔离级别下工作,其他两个隔离级别和MVCC是不兼容的。因为未提交读,总数读取最新的数据行,而不是读取符合当前事务版本的数据行。而串行化(Serializable)则会对读的所有数据多加锁。

主要思想是:InnoDB通过undo log保存每条数据的多个版本,并且能够找回数据历史版本提供给用户读,每个事务读到的数据版本可能是不一样的。在同一个事务中,用户只能看到该事务创建快照之前已经提交的修改和该事务本身做的修改。

二、当前读和快照读

  • 快照读:读取的是历史数据,不加锁的简单 Select 都属于快照读。
select * from user where id = 1;
  • 当前读:读取的是最新数据,而不是历史的数据,加锁的 SELECT,或者对数据进行增删改都会进行当前读。
SELECT * FROM user LOCK IN SHARE MODE;
SELECT * FROM user FOR UPDATE;
INSERT INTO user values ...
DELETE FROM user WHERE ...
UPDATE user SET ...

三、MVCC 与快照读的关系

MVCC 多版本并发控制是维持一个数据的多个版本,使得读写操作没有冲突,而这只是一个抽象概念。而快照读就是 MySQL 实现 MVCC 理想模型的其中一个非阻塞读功能,快照读所读取的就是MVCC维持的多版本数据中去某个版本数据。

四、MVCC 优点

  1. 提供多版本数据,在并发读写数据库时,读写操作互不影响,提高了数据库并发读写的性能。
  2. 可以解决脏读,幻读,不可重复读等事务隔离问题。

五、MVCC 实现原理

主要是依赖每一行记录中2个隐藏字段、undo log版本链 以及 ReadView。

1. 行记录的隐藏字段
  1. trx_id:操作这个数据的事务 ID,也就是最后一个对数据插入或者更新的事务 ID 。
  2. roll_ptr:回滚指针,指向这个记录的 Undo Log 信息。
  3. row_id:隐藏的行 ID ,用来生成默认的聚集索引。如果创建数据表时没指定聚集索引,这时 InnoDB 就会用这个隐藏 ID 来创建聚集索引。
2. undo log版本链

多个事务并行操作某一行数据时,不同事务对该行数据的修改会产生多个版本,然后通过回滚指针(roll_pointer),连成一个链表,这个链表就称为版本链。(其实undo log 版本链的节点在事务提交之后可能是会 purge 线程清除掉的)

(1)首先开启第一个事务,事务id为1,通过insert语句往表中插入一条新记录如下:
在这里插入图片描述
由于是新插入的记录,因此它的roll_pointer指向的undo log为空。

(2)接着开启第二个事务,事务id为2,更新该行记录的name为Tom。
在这里插入图片描述

  • 在第二个事务修改该行记录时,数据库会先对该行加排他锁;
  • 然后把该行数据拷贝到 undo log 中,作为旧版本记录;
  • 拷贝完毕后,再修改该行name为Tom,并且修改隐藏字段trx_id为当前事务的id, 回滚指针roll_pointer指向拷贝到 undo log 的副本记录,既表示我的上一个版本就是它。
  • 事务提交后,释放锁。

(3)再开启第三个事务,事务id为3,修改改行记录的age为25。
在这里插入图片描述

  • 在第三个事务修改该行记录时,数据库会先对该行加排他锁;
  • 然后把该行数据拷贝到 undo log 中,作为旧版本记录;
  • 拷贝完毕后,再修改该行age为25,并且修改隐藏字段trx_id为当前事务的id, 回滚指针roll_pointer指向拷贝到 undo log 的副本记录,既表示我的上一个版本就是它。
  • 事务提交后,释放锁。
3.ReadView

Read View 就是事务进行 “快照读” 操作时候生产的 “读视图”,在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的 ID。主要是用来做可见性判断的,即当我们某个事务执行快照读的时候,当前事务能够看到undo log版本链上的哪个版本数据。

(1)ReadView中主要属性

  1. trx_ids:当前系统中那些活跃(未提交)的读写事务ID,它数据结构为一个List。(trx_ids中的活跃事务不包括:当前事务自己)。
  2. min_trx_id:trx_ids中最小的事务id。
  3. max_trx_id:预分配事务编号,MySQL即将为下一个事务分配的事务id。
  4. creator_trx_id: 表示生成该 ReadView 的事务的 事务id。

(2)ReadView可见性判断规则

  1. 判断 trx_id = creator_trx_id,如果条件成立,则说明当前事务与进行select快照读的事务是同一个事务,那么该select是可以读取到该trx_id对应的版本;如果条件不成立,继续往下判断其他条件。
  2. 判断 trx_id < min_trx_id,如果条件成立,则说明当前事务是在进行select快照读的事务之前就已经提交了,那么该select是可以读取到该trx_id对应的版本;如果条件不成立,继续往下判断其他条件。
  3. 判断 trx_id > max_trx_id,如果条件成立,则说明当前事务是在进行select快照读的事务之后才创建的,那么该select是肯定读取不到该trx_id对应的版本;如果条件不成立,则继续往下判断其他条件。
  4. 判断 min_trx_id < trx_id < max_trx_id,如果条件成立,则说明当前事务可能在活跃的事务中,需要再判断下trx_id是否在trx_ids中,如果不在,则说明当前事务已经提交过了,那么该select就可以读取到该trx_id对应的版本;否则说明当前事务还未提交,该select也就无法读取到该trx_id对应的版本。

(3)已提交读(RC)与可重复读(RR)级别下的快照读
RC 隔离级与RR隔离级生成Read View 的时机是不同的,因为也造成了两者快照读的结果的不同。在 RC 隔离级别下,是每个快照读都会生成并获取最新的 Read View;而在 RR 隔离级别下,则是同一个事务中的第一个快照读才会创建 Read View, 之后的快照读获取的都是同一个 Read View。

undo log版本链:
在这里插入图片描述
ReadView创建实时机:
在这里插入图片描述

解析:
(1)RC级别下:
在事务D中的第一个select语句执行时,生成的ReadView中,当前系统中那些活跃(未提交)的读写事务有{3,4},创建ReadView的事务id为5,活跃事务中最新事务id为3,预分配的事务id为6。再根据undo log版本链依次与ReadView的可见性判断规则进行对比,判断哪个版本是可见的。例如:

  • 先对版本链最新的一个版本trx_id = 4进行判断:
    1.先判断 trx_id = creator_trx_id:creator_trx_id = 5,trx_id = 4,条件不成立,暂时无法证明该版本相对于当前select可见,则继续根据其他规则进行判断。
    2.继续判断 trx_id < min_trx_id:min_trx_id = 3,trx_id = 4,条件不成立,也暂时无法证明该版本相对于当前select可见,则继续根据其他规则进行判断。
    3.继续判断 trx_id > max_trx_id:max_trx_id = 6,trx_id = 4,条件不成立,也暂时无法证明该版本相对于当前select可见,则需要继续据其他规则进行判断。(如果该条件成立,则可以证明该版本相对于当前select肯定是不可见的)
    4.继续判断 min_trx_id < trx_id < max_trx_id:条件成立,说明当前事务可能在活跃的事务中,需要再判断下trx_id是否在trx_ids中,trx_id = 4在活跃的事务中,也就是当前事务还未提交,那么该select也就无法读取到该版本的数据。
    所有可见性规则判断完毕,最终得出版本链中最新的一个事务C这个版本在事务D中的第一个select语句是不可见的。
  • 再对版本链中trx_id = 3 按照上述的可见性规则依次判断:最终得出该版本在事务D中的第一个select语句也是不可见的。
  • 再对版本链中trx_id = 2 按照上述的可见性规则依次判断:最终得出该版本在事务D中的第一个select语句也是可见的。

在事务D中的第二个select语句执行时,会重新生成一个新的ReadView,此时系统中那些活跃(未提交)的读写事务有{4},创建ReadView的事务id为5,活跃事务中最新事务id为4,预分配的事务id为6。再根据undo log版本链依次与ReadView的可见性判断规则进行对比,可以得出最终该select语句的可见版本为 trx_id = 3 和 trx_id = 2,与第一个select语句查询的可见版本不一样。这也是为什RC隔离级别下,同一事务中多次使用快照读查询时会产生查询结果不一致的问题。

(2)RR级别下:
在事务D中的第一个select语句执行时,生成一个ReadView与RC级别是一样的,所以最终得到的可见版本也是只有 trx_id = 2。但是在事务D中的第二个select语句执行时,RR级别不会再生成新的ReadView,而是直接复用第一次生的的那个ReadView,所以最终判断下来,第二个select语句的可见版本也只有 trx_id = 2。这也就是为什么RR级别下同一事务中多次使用快照读查询时结果都是相同的原因。如何在事务中使用了当前读,则后面的快照读不会再复用之前的ReadView,而是重新生成一个新的ReadView,这也RR级别下无法解决幻读的原因。

相关文章:

MySQL事务MVCC详解

一、概述 MVCC (MultiVersion Concurrency Control) 叫做多版本并发控制机制。主要是通过数据多版本来实现读-写分离&#xff0c;做到即使有读写冲突时&#xff0c;也能做到不加锁&#xff0c;非阻塞并发读&#xff0c;从而提高数据库并发性能。 MVCC只在已提交读&#xff08…...

SQL RDBMS 概念

SQL RDBMS 概念 RDBMS是关系数据库管理系统(Relational Database Management System)的缩写。 RDBMS是SQL的基础&#xff0c;也是所有现代数据库系统(如MS SQL Server、IBMDB2、Oracle、MySQL和MicrosoftAccess)的基础。 关系数据库管理系统(Relational Database Management Sy…...

onlyoffice的介绍搭建、集成过程。Windows、Linux

文章目录 什么是onlyoffice功能系统要求安装必备组件 windows搭建资源下载安装数据库onlyoffice安装测试 Linux搭建dockerdocker-compose 项目中用到的技术&#xff0c;做个笔记哈~ 什么是onlyoffice 在本地服务器上安装ONLYOFFICE Docs Community Edition Community Edition…...

37. 解数独

编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图&#xff09; 数独部分空…...

git cherry-pick 合并某次提交

一、无冲突的情况 1、合并其它分支某次提交 切换到主分支&#xff0c;想把其他分支的某次commit修改 合并到主分支上&#xff0c; 可以用 git cherry-pick 命令 比如&#xff0c;其它分支&#xff0c;某次提交的commit Hash 是30e48158badc39801f1ce3cb375a07b872d6f220 &a…...

【面试HOT100】子串普通数组矩阵

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于LeetCodeHot100进行的&#xff0c;每个知识点的修正和深入主要参考…...

XPSpeak软件教程-科学指南针

在做X 射线光电子能谱(XPS)测试时&#xff0c;科学指南针检测平台工作人员在与很多同学沟通中了解到&#xff0c;好多同学仅仅是通过文献或者师兄师姐的推荐对XPS测试有了解&#xff0c;但是对于其软件操作还属于小白阶段&#xff0c;针对此&#xff0c;科学指南针检测平台团队…...

NLP算法面经 | 腾讯 VS 美团

作者 | 曾同学 编辑 | NewBeeNLP 面试锦囊之面经分享系列&#xff0c;持续更新中 后台回复『面试』加入讨论组交流噢 lz从3月初脚因打球扭伤了开始&#xff0c;投递简历&#xff0c;接二连三的面试鞭尸又面试&#xff0c;昨天才终于上岸了&#xff0c;分享经验~ 腾讯PCG看点&…...

【广州华锐互动】塔吊多人安拆VR互动培训系统

塔吊多人安拆VR互动培训系统由广州华锐互动制作&#xff0c;是一种基于VR技术的模拟实训系统&#xff0c;专门用于培训塔吊驾驶员和操作员。 在现实生活中&#xff0c;塔吊操作具有一定的危险性&#xff0c;尤其是在培训过程中容易发生意外。而使用VR互动实训系统&#xff0c;学…...

Linux性能优化--性能工具:特定进程内存

5.0 概述 本章介绍的工具使你能诊断应用程序与内存子系统之间的交互&#xff0c;该子系统由Linux内核和CPU管理。由于内存子系统的不同层次在性能上有数量级的差异&#xff0c;因此&#xff0c;修复应用程序使其有效地使用内存子系统会对程序性能产生巨大的影响。 阅读本章后&…...

MyLife - Docker安装rabbitmq

Docker安装rabbitmq 个人觉得像rabbitmq之类的基础设施在线上环境直接物理机安装使用可能会好些。但是在开发测试环境用docker容器还是比较方便的。这里学习下docker安装rabbitmq使用。 1. rabbitmq 镜像库地址 rabbitmq 镜像库地址&#xff1a;https://hub.docker.com/_/rabbi…...

Leetcode刷题详解——长度最小的子数组

1. 题目链接&#xff1a;209. 长度最小的子数组 2. 题目描述&#xff1a; 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度**。**如果不…...

客流人数管理新趋势:景区客流采集分析系统的功能特点

随着旅游业的蓬勃发展&#xff0c;越来越多的人选择前往景区进行休闲和旅游。然而&#xff0c;人流量的增加也给景区管理带来了一系列的挑战。为了更好地管理和运营景区&#xff0c;景区客流采集分析系统应运而生。 一、案例展示 二、产品卖点 该系统利用先进的人工智能算法和…...

【仙逆】王林极限跑酷,藤厉自食恶果,仙逆战斗获好评,张虎命运被改写

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 最新一集《仙逆》已经更新&#xff0c;相信很多小伙伴都已经先睹为快&#xff0c;在击杀了白展之后&#xff0c;张虎和王林担心其师傅即墨老人报复&#xff0c;因此躲到看似安全的藤家城&#xff0c;以为那里有…...

想要精通算法和SQL的成长之路 - 前缀和的应用

想要精通算法和SQL的成长之路 - 前缀和的应用 前言一. 区域和检索 - 数组不可变二. 二维区域和检索 - 矩阵不可变2.1 前缀和的计算2.2 用前缀和计算二维区域和 三. 矩形区域不超过 K 的最大数值和 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 区域和检索 - 数组不可变 原…...

如何让大模型自由使用外部知识与工具

本文将分享为什么以及如何使用外部的知识和工具来增强视觉或者语言模型。 全文目录&#xff1a; 1. 背景介绍 OREO-LM: 用知识图谱推理来增强语言模型 REVEAL: 用多个知识库检索来预训练视觉语言模型 AVIS: 让大模型用动态树决策来调用工具 技术交流群 建了技术交流群&a…...

关注用户信息卡片

效果展示 CSS 知识点 box-shadow 属性回顾CSS 变量回顾 实现页面整体布局 <div class"card"><div class"box"><!-- 视频 --><div class"vide_box"><video src"user.mp4" type"video/mp4" aut…...

【Java基础面试十八】、说一说重写与重载的区别

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;说一说重写与重载的区别…...

Linux文件管理(上)

一、VIM编辑器 1、vi概述 vi&#xff08;visual editor&#xff09;编辑器通常被简称为vi&#xff0c;它是Linux和Unix系统上最基本的文本编辑器&#xff0c;类似于Windows 系统下的notepad&#xff08;记事本&#xff09;编辑器。 2、vim编辑器 Vim(Vi improved)是vi编辑器…...

docker 复习

文章目录 1. docker 基础1.1 docker 安装配置镜像加速器拉取镜像的仓库&#xff1a; docker 部署Mysql 镜像docker 命令的详细解释docker 常见命令docker 数据卷docker 相关命令总结 2.自定义镜像2.1 dockerfile2.2 try 构建一个Java镜像&#xff0c;并部署2.3 总结: 3. docker…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...