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

    • 什么是事务
          • 原子性:
          • 一致性
          • 隔离性
        • 问题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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【单片机通讯协议】—— 常用的UART/I2C/SPI等通讯协议的基本原理与时序分析

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、通信基本知识1.1 MCU的参见外设1.2 通信的分类按基本的类型从传输方向上来分 二、UART(串口通讯)2.1 简介2.2 时序图分析2.3 UART的…

Ceph 手动部署(CentOS9)

#Ceph手动部署、CentOS9、squid版本、数字版本19.2.0 #部署服务:块、对象、文件 一、部署前规划 1、兼容性确认 2、资源规划 节点类型节点名称操作系统CPU/内存硬盘网络组件安装集群节点CephAdm01CentOS94U/8GOS:40G,OSD:2*100GIP1:192.169.0.9(管理&集群),IP2:…

CentOS7 解决ping:www.baidu.com 未知的名称或服务

CentOS7 解决ping:www.baidu.com“未知的名称或服务 在VM查看网络配置 查看虚拟网络编辑器 编辑网络配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33注意:不同机器的配置文件名可能不相同,通过 ip addr 命令查看 将 ONBOOT 从 no 改…

GPU 进阶笔记(二):华为昇腾 910B GPU

大家读完觉得有意义记得关注和点赞!!! 1 术语 1.1 与 NVIDIA 术语对应关系1.2 缩写2 产品与机器 2.1 GPU 产品2.2 训练机器 底座 CPU功耗操作系统2.3 性能3 实探:鲲鹏底座 8*910B GPU 主机 3.1 CPU3.2 网卡和网络3.3 GPU 信息 3.3…

[ICCD 2022]Towards Sparsification of Graph Neural Networks

论文网址:[2209.04766] Towards Sparsification of Graph Neural Networks 论文代码:github.com 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正&#…

人工智能与传统编程的主要区别是什么?

传统编程:开发者预先编写软件行为规则,代码基于程序员定义逻辑处理输入并产生确定输出,具有确定性、手动编写规则和结构化逻辑特点,如垃圾邮件分类程序基于预设关键词等规则。AI 编程:从数据中学习而非手动编写规则&am…

Mac电脑python多版本环境安装与切换

我当前是python3.9.6环境,需要使用3.9.8环境,通过brew安装3.9.8版本,然后通过pyenv切换环境 步骤 1: 安装 pyenv brew install pyenv brew install pyenv-virtualenv 步骤 2: 安装 Python 3.9.8(使用 pyenv 安装指定版本的 Pyth…

UE5通过蓝图节点控制材质参数

通过蓝图节点控制材质的参数 蓝图节点 在材质上设置标量值 和 在材质上设置向量参数值 Set Scalar Parameter Value on Materials Set Vector Parameter Value on Materials 这两个蓝图节点都可以在蓝图中,控制材质的参数值和向量值

人工智能(AI)简史:推动新时代的科技力量

一、人工智能简介 人工智能(AI,Artificial Intelligence)是计算机科学的一个分支,旨在研究和开发可以模拟、扩展或增强人类智能的系统。它涉及多种技术和方法,包括机器学习、深度学习、自然语言处理(NLP&a…

Github优质项目推荐(第十期)

文章目录 Github优质项目推荐(第十期)一、【postiz-app】,14.6k stars - 您的终极 AI 社交媒体调度工具二、【lobe-chat】,50.1k stars - AI 聊天框架三、【cobalt】,22.1k stars - 媒体下载器四、【build-your-own-x】…

DeepSeek V3“报错家门”:我是ChatGPT

搜 :海讯无双Ai 要说这两天大模型圈的顶流话题,那绝对是非DeepSeek V3莫属了。 不过在网友们纷纷测试之际,有个bug也成了热议的焦点—— 只是少了一个问号,DeepSeek V3竟然称自己是ChatGPT。 甚至让它讲个笑话,生成…

通过 4 种方法将数据从 OnePlus 传输到Android

概括 由于它们是不同的品牌,因此将数据从 OnePlus 传输到Android是否很困难?也许您可以从这篇介绍 OnePlus 到Coolmuster Android数据传输的 4 个实用解决方案的文章中获得帮助。学习完它们后,您将有一个顺利的转移过程,所以为什…

Spring Boot的开发工具(DevTools)模块中的热更新特性导致的问题

问题: java.lang.ClassCastException: class cn.best.scholarflow.framework.system.domain.entity.SysUser cannot be cast to class cn.best.scholarflow.framework.system.domain.entity.SysUser (cn.best.scholarflow.framework.system.domain.…

频域滤波为什么使用psf2otf函数?

MATLAB中circshift函数是psf2otf函数的核心,在MATLAB中circshift函数的原理分析——psf2otf函数的核心直观解释了为什么需要循环移位。 MATLAB提出了psf2otf函数,先做循环移位,再计算离散傅里叶变换。如果有空域的卷积核,通过这个…

计算机网络-L2TP Over IPSec基础实验

一、概述 上次我们进行了标准L2TP的配置,但是在最后我们在进行业务流量访问时看到流量是没有进行加密的,这就导致可能得安全风险,所以这里其实可以退像GRE那样调用IPSec框架来进行加密保护。 拓扑 数据不加密 现在需要配置IPSec,然…

springboot3整合knife4j详细版,包会!(不带swagger2玩)

1. 引入依赖 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.4.0</version> </dependency>2. 配置文件 简短必要版 # 配置springd…

Mac 安装Mysql启动Mysql以及数据库的常规操作

Mac 安装Mysql启动Mysql以及数据库的常规操作 一、mysql的安装 1、登录官方网站:dev.mysql.com/downloads/mysql/ 二、查看系统架构 uname -m 在MAC中&#xff1a; 如果输出结果是 x86_64&#xff0c;则表示你的系统是 x86-64 架构。 如果输出结果是 arm64&#xff0c;则表示…

module ‘django.db.models‘ has no attribute ‘FieldDoesNotExist‘

module ‘django.db.models’ has no attribute ‘FieldDoesNotExist’ xadmin报错 原因 django与xadmin版本不匹配。 django==3.2.7 xadmin-django==3.0.2解决方案 在xadmin/view/edit.py的388行改为 from django.core import exceptions if self.request_method ==

马斯克X-AI发布了文生图模型Aurora,已经集成到聊天机器人Grok中。

千呼万唤&#xff0c;马斯克X-AI发布了文生图模型Aurora&#xff0c;并将其整合进了聊天机器人Grok中。Aurora不仅支持文本输入&#xff0c;还可从用户提供的图像中获取灵感&#xff0c;或直接编辑用户上传的图像。 Aurora 是一个自回归混合专家网络&#xff0c;经过训练可以从…

如何在IDEA一个窗口中导入多个项目

一般在IDEA窗口中想导入一个新项目&#xff0c;会提示我们在当前窗口还是新窗口。如果选新窗口&#xff0c;就会新打开一个窗口&#xff0c;此时新窗口里面只有新导入的项目。 而为了浏览起来更方便&#xff0c;需要实现在IDEA一个窗口中导入多个项目。具体步骤如下&#xff1…