MySQL 的事务与多版本并发控制(MVCC)的那些事

news2025/1/7 13:41:50

    • 什么是事务
          • 原子性:
          • 一致性
          • 隔离性
        • 问题1: 为什么MySQL要使用mvcc实现隔离性而不使用 锁 解决并发问题?
          • 持久性
        • 问题2: MySQL 不是磁盘数据库吗,持久化为什么是 redo log 保证的?
        • 问题 3: redo log 储存了什么东西,持久化(崩溃恢复是怎么做的?)
        • 问题 4 : MySQL 的 bing log (二进制日志)已经有全量的数据,为什么还要使用 redo 做崩溃恢复,为什么不直接使用 bin log做崩溃恢复.
        • 问题 5 :redo log与 bin log 如何保证数据的一致性?
    • MySQL 的 MVCC 多版本并发控制
      • 事务的read view(事务能感应到的数据有哪些?)
    • 事务的隔离级别
        • 读未提交
          • 脏读问题
        • 读提交
          • 不可重复读问题
          • 幻读问题
        • 可重复读(默认级别)
        • 串行化
        • 问题 6 : 可重复读可以完全避免幻读的问题吗?
        • 问题 7 : 你们公司(之前的业务)使用的什么隔离级别?

MySQL 数据的版本链(undo log)

MySQL 的数据有两个隐藏列,

  • 第一是当前数据的版本(修改数据的事务 id)
  • 第二的指向数据之前状态的指针(指向的是一行 undo log 日志)
    在这里插入图片描述
    这样我们的数据就像链条一样可以获取到之前数据的版本(做回滚与 mvcc 都非常有用)

什么是事务

ACID

原子性:

任务要么全部成功要么全部失败,不存在只执行一部分的情况

  • 原子性是通过undo log(回滚日志),当事务失败就会将数据回滚到之前的状态
一致性
  • 事务前后始终保持一致性约束: 比如之前有唯一键约束,事务后也保持唯一键约束.(程序按照程序员的规则运行)
隔离性
  • 多事务并行的时候是相互不影响的(通过 mvcc 实现 : 多版本并发控制)
问题1: 为什么MySQL要使用mvcc实现隔离性而不使用 锁 解决并发问题?
  1. 锁会阻塞其他的事务,而多版本并发控制,通过数据版本链事务能感应到的数据,可以避免阻塞.–提高性能
  2. 锁并不满足事务(多个任务)的原子性,如果事务失败需要通过版本链将全部的任务修改的数据都回到事务开启前的状态
  3. 所以 MySQL 是锁与 mvcc 共用一起保证事务的隔离与原子性(比如修改单行数据:事务先上行排他锁,执行任务;事务提交后再释放锁),这样可以避免数据更新丢失的问题并且可以在失败的时候将数据回滚到之前的状态.
持久性
  • 事务提交后数据将持久化,不会因为故障丢失数据(redo log(重做日志) 实现)
问题2: MySQL 不是磁盘数据库吗,持久化为什么是 redo log 保证的?
  1. 数据持久化磁盘的消耗比较大(慢),MySQL 储存数据的流程是
    • 先存缓冲区(内存),再找合适的时机落盘,这样性能会高非常多(内存的 io 有百万,千万级 qps)
    • 但是如果数据没来得及落盘,服务就崩溃了(断电),那么数据就有丢失的风险

redo log(重做日志): 解决崩溃恢复的数据丢失问题

  1. redo log会记录写(命令)数据的偏移量(数据做了什么修改)
  2. redo log会通过追加的形式将日志记录到磁盘
  3. redo log 的落盘机制(可以设置的)
    • 事务提交立即落盘
    • 事务提交落用户缓冲区(每隔 1s,自动落盘/占用缓冲区一半自动落盘)-只要 MySQL 服务宕机数据就会丢
    • 事务提交落内核缓存(由内核缓存决定落盘时机)-只要操作系统正常数据就不会丢
  • 记录 redo log 比数据落盘更快,因为日志是顺序写(追加的形式),而数据直接落盘需要找到数据对应的位置
问题 3: redo log 储存了什么东西,持久化(崩溃恢复是怎么做的?)
  1. redo log会记录写(命令)数据的偏移量(数据做了什么修改)
  2. redo log会通过追加的形式将日志记录到磁盘
  3. redo log 的落盘机制(可以设置的)
    • 事务提交立即落盘
    • 事务提交落用户缓冲区(每隔 1s,自动落盘/占用缓冲区一半自动落盘)-只要 MySQL 服务宕机数据就会丢
    • 事务提交落内核缓存(由内核缓存决定落盘时机)-只要操作系统正常数据就不会丢
  • 记录 redo log 比数据落盘更快,因为日志是顺序写(追加的形式),而数据直接落盘需要找到数据对应的位置
问题 4 : MySQL 的 bing log (二进制日志)已经有全量的数据,为什么还要使用 redo 做崩溃恢复,为什么不直接使用 bin log做崩溃恢复.
  • bin log 是一个比较重的服务,因为是储存全量的数据,文件比较大,一个文件写满了会创建新的文件继续写(无限空间),并且 bin log是不会默认开启的,而是手动的开启(需要数据备份,或者配置主从才会使用)

  • redo log 是一个比较轻的服务,专门做数据的崩溃恢复的,他只记录近期的数据(没有持久化到磁盘的数据),采用的循环写的策略,如果 redo log 写满了,会循环覆盖之前的内容,所以消耗的空间是有限的

  • bin log当然可以做数据恢复,因为也是追加的数据修改的日志(可以做全量数据恢复的东西自然可以做数据崩溃的恢复)

  • 没有必要只为了数据恢复而强制开启一个比较重的服务(bin log),有点拿大炮打苍蝇的感觉

问题 5 :redo log与 bin log 如何保证数据的一致性?

为什么要一致性?

  1. bin log是配置主从的,从数据库复制的 bin log
  2. 如果数据不一致,那么数据主从数据库的数据就会不一致

redo log 是事务开始的时候就会记录(用于事务途中的崩溃回滚)
bin log 是事务提交时记录的,事务提交数据更新生效,同步从节点数据

redo log 双写:

  1. 写的命令执行前:记录 redo log ,登记为待提交状态

    • 这时候崩溃,就会回滚,不生效
  2. 事务提交:记录 bin log,再将 redo log 登记为提交状态

    • binlog 记录成功后将 redo log 登记为生效状态,避免 redo log 与 bin log 数据不一致导致的主从数据不一致问题

(问: 什么先记录 redo log,崩溃恢复 redo log 再刷的时候 也可以重新记录 没记录的 bin log? 搞不懂)

MySQL 的 MVCC 多版本并发控制

事务的read view(事务能感应到的数据有哪些?)

read view

  • 事务号(id)
  • 当前活跃事务列表(ids) : 表示已经开始但是没有提交的事务
  • 事务开始时列表中最小的事务号min: 事务开始时最小的活跃事务 id
  • 事务开始时列表中最大的事务号+1(max): 事务开始时最大的活跃事务 id+1

哪些数据版本是当前事务可见的?

提交可见原则:

  1. 小于(min)的数据版本是可见的:小于min 说明事务开启前,该版本的数据已经提交生效了
  2. 小于 max 但是不再 ids(活跃列表中的)是可见的:
    • 小于 max 表示事务开启前,改版本的事务已经开启(这是前提,因为>= max表示事务开启时,该数据的事务并没有开启,肯定是不可见的),
    • 不在 ids 中的事务:不在 ids 中表示事务已经提交,证明数据可见

MySQL 事务就根据数据的版本链找到自己可以感应到的数据的版本进行读取,实现多版本并发控制

事务的隔离级别

读未提交

读取版本链中最新的版本的数据(不判断是否可见)

脏读问题
  • 事务 b 修改一条数据(未提交),事务 a 读取这条数据,这时 b 事务回滚,事务 a 再一次读取这个数据
  • 这时事务 a 中两次读取的数据的结果是不一样的,这就是脏读
读提交

通过 read view 读取自己能感应到的最新版本的数据

  • 可以避免脏读的问题
不可重复读问题
  • 事务 a 读取一条数据,之后事务 b 修改这条数据(提交),事务 a 再一次读取数据,
  • 这时事务 a 中两次读取的数据的结果是不一样的,这就是不可重复读
    (思考: 事务在查询的时候已经持有该条数据的资源(共享锁),其他事务就无法操作该数据(加排他锁),还会有不可重复读的问题吗?
幻读问题
  • 事务 a 读取m 到 n 区间的数据, 之后事务 b 添加一条 m 到 n 区间的数据 ,事务 a 再一次读取m 到 n 区间的数据数据,
  • 这时事务 a 中两次读取的数据的结果(条数)是不一样的,这就是幻读.
可重复读(默认级别)
  • 也是通过 read view 读取自己可以感应到的数据的版本,

  • 但是不同的是,可重复读的活跃事务列表(ids)是一个拷贝,不会变化,所以只能读取到事务开始时数据的样子,中间就算有提交的更改也是感应不到的

  • 可以避免不可重复读与幻读(一定程度上)问题

串行化
  • 前一个事务执行完成,下一个事务才能执行
  • 就类似单线程依次的执行,一般很少使用,性能太低
问题 6 : 可重复读可以完全避免幻读的问题吗?

不可以,有两种情况可重复读还是会出现幻读

  1. 事务 A(读区间,更改区间,再读区间);事务 B(在事务 A期间,更改前插入或者删除了某条数据),会出现幻读的情况
  2. 事务A先用读快照(普通 select), 事务 B 插入一条数据,再使用读当前(select…for update)就会出现幻读

可以理解update 是要使用最新的数据进行 update,就会去发现最新的数据,可见范围就变了,就出现了幻读.

问题 7 : 你们公司(之前的业务)使用的什么隔离级别?
  • 很多时候不会在意,重复读,幻读的问题(很少有人会再同一个事务中做两次相同的查询/范围)
  • 所以一般情况下:读提交的隔离级别就已经够用了
  • 所以很多团队会选择读提交的隔离级别,而不是默认的可重复读
  • 为什么?
    • 隔离级别越高性能越低,读提交的性能要稍微好一点.

参考
https://blog.csdn.net/dengjiayue/article/details/144537660?fromshare=blogdetail&sharetype=blogdetail&sharerId=144537660&sharerefer=PC&sharesource=dengjiayue&sharefrom=from_link

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Eplan 项目结构(高层代号、安装地点、位置代号)

Eplan中的项目结构分为3个层次: (1)功能面结构。指明这个系统的功能,有什么用途。在EPlan中,指的就是"高层代号()"。 一般指的是线体。 (2)位置面结构。指明该…

OWASP ZAP之API 请求基础知识

ZAP API 提供对 ZAP 大部分核心功能的访问,例如主动扫描器和蜘蛛。ZAP API 在守护进程模式和桌面模式下默认启用。如果您使用 ZAP 桌面,则可以通过访问以下屏幕来配置 API: Tools -> Options -> API。 ZAP 需要 API 密钥才能通过 REST API 执行特定操作。必须在所有 …

短信通知在 IOS 17/18 中不起作用?这是修复方法

问题 “我最近将 iPhone 更新到了 iOS 17/18。我真的很兴奋,直到我发现 iOS 17/18 中没有 iMessage 文本通知。此后我的兴奋变成了失望。请告诉我如何解决这个问题? ” 我们知道这可能是一个大问题,因为我们通常不会打开消息应用程序&#…

从0开始的opencv之旅(1)cv::Mat的使用

目录 Mat 存储方法 创建一个指定像素方式的图像。 尽管我们完全可以把cv::Mat当作一个黑盒,但是笔者的建议是仍然要深入理解和学习cv::Mat自身的构造逻辑和存储原理,这样在查找问题,或者是遇到一些奇奇怪怪的图像显示问题的时候能够快速的想…

机场安全项目|基于改进 YOLOv8 的机场飞鸟实时目标检测方法

目录 论文信息 背景 摘要 YOLOv8模型结构 模型改进 FFC3 模块 CSPPF 模块 数据集增强策略 实验结果 消融实验 对比实验 结论 论文信息 《科学技术与工程》2024年第24卷第32期刊载了中国民用航空飞行学院空中交通管理学院孔建国, 张向伟, 赵志伟, 梁海军的论文——…

《Rust权威指南》学习笔记(二)

枚举enum 1.枚举的定义和使用如下图所示: 定义时还可以给枚举的成员指定数据类型,例如:enum IpAddr{V4(u8, u8, u8, u8),V6(String),}。枚举的变体都位于标识符的命名空间下,使用::进行分隔。 2.一个特殊的枚举Option&#xff0…

OSI模型的网络层中产生拥塞的主要原因?

( 1 )缓冲区容量有限;( 1.5 分) ( 2 )传输线路的带宽有限;( 1.5 分) ( 3 )网络结点的处理能力有限;( 1 分…

linux上安装MySQL教程

1.准备好MySQL压缩包,并进行解压 tar -xvf mysql-5.7.28-1.el7.x86_64.rpm-bundle.tar -C /usr/local 2.检查是否有mariadb数据库 rpm -aq|grep mariadb 关于mariadb:是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目…

R语言中的时间序列分析·

1 数据集说明 AirPassengers 1949~1960年每月乘坐飞机的乘客数 JohnsonJohnson Johnson&Johnson每股季度收入 nhtemp 康涅狄格州纽黑文地区从1912年至1971年每年的平均气温 Nile 尼罗河的流量 sunspots 1749年~1983年月平均太阳黑子数 2 相关包 xts、forecast、tser…

LookingGlass使用

背景 Looking Glass 是一款开源应用程序,可以直接使用显卡直通的windows虚拟机。 常见环境是Linux hostwindows guest,基本部署结构图: 编译 git clone --recursive https://github.com/gnif/LookingGlass.git编译client mkdir client/b…

HCIA-Access V2.5_7_3_XG(S)原理_关键技术

为什么需要测距 因为上行链路只有一根纤,而且每一个ONU到OLT的距离是不一样的,虽然上行通过TDMA技术,让每一个ONU在不同的时间段发送数据,但是仍然有可能在同一时刻到达分光器,产生数据冲突。 有测距的信元传输 所以为了避免碰撞冲突,通过ONU在注册的时候就会启动测距…

四、VSCODE 使用GIT插件

VSCODE 使用GIT插件 一下载git插件与git Graph插件二、git插件使用三、文件提交到远程仓库四、git Graph插件 一下载git插件与git Graph插件 二、git插件使用 git插件一般VSCode自带了git,就是左边栏目的图标 在下载git软件后vscode的git插件会自动识别当前项目 …

RISC-V学习笔记

1.RISC ISA1个基本整数指令集多个可选的扩展指令集,如RV32I表示支持32位整数指令集。I表示基本指令集,M表示整数乘法与除法指令集,A表示存储器原子指令集,F表示单精度浮点指令集,D表示双精度浮点指令集等,C…

strapi中使用Documentation插件

Swagger UI 自动生成并展示了 API 的文档,这些文档是根据 OpenAPI Specification (OAS) 格式编写的。它提供了对 API 端点、请求方法(GET, POST, PUT, DELETE 等)、参数、响应格式等详细信息的描述 安装 npm run strapi install documentat…

AI来帮忙:蛋白纯化不用慌

在当今生物学研究的前沿领域,从探索疾病的发病机制,到新型药物的研发,再到生物工程产品的制造,高纯度、高活性的蛋白质都是不可或缺的基石。 科研人员在蛋白纯化的征程中,时常被诸多难题困扰。一方面,生物…

SpringCloud系列教程:微服务的未来(六)docker教程快速入门、常用命令

对于开发人员和运维工程师而言,掌握 Docker 的基本概念和常用命令是必不可少的。本篇文章将带你快速入门 Docker,并介绍一些最常用的命令,帮助你更高效地进行开发、测试和部署。 目录 前言 快速入门 docker安装 配置镜像加速 部署Mysql …

基于单片机中药存放环境监测系统的实现

基于单片机中药存放环境监测系统的实现 项目开发背景 随着现代中药的广泛应用,中药材的存储环境对其质量有着至关重要的影响。温湿度、烟雾、火灾等环境因素,若不加以控制,将会导致中药材失效或变质。因此,设计一个基于单片机的…

casaos安装最新版homeassistant-arm

进入cosOS界面点自定义安装 Docker镜像:homeassistant/armv7-homeassistant Tag:2024.12.2 标题:Home Assistant 图片路径:https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStoremain/Apps/HomeAssistant/icon.png Web UI:http&…

Fabric环境部署-安装Go

安装go语言环境 国内镜像:Go下载 - Go语言中文网 - Golang中文社区 1.选择版本下载后解压:注意go1.11.linux-amd64.tar.gz换成你下的 sudo tar zxvf go1.21.linux-amd64.tar.gz -C /usr/local 2.. 创建Go目录 mkdir $HOME/go 3. 用vi打开~./bashrc&…

慧集通(DataLinkX)iPaaS集成平台-主数据映射管理(多系统间基础档案的映射)

主数据管理 主数据管理主要是解决不同业务系统之间历史数据不统一的问题,在该功能下主要分为三个模块分别为数据对象、应用系统、数据映射; 其中数据对象指的是我们的不同的对象,如:部门、人员、职级、科目、供应商等等&#xff…