深度整理总结MySQL——事务专辑

news2024/12/24 20:59:01

事务

    • 前言
    • 什么是事务
      • 事务的特性
      • 事务的状态
      • 事务会引发什么问题?
      • 解决事物引发的问题手段
    • 事务日志
      • Undo Log 日志
        • 简单介绍
        • 具体实现
      • Buffer Pool
          • Buffer Pool缓存什么?
      • Redo Log日志
        • 为什么需要Redo Log?
        • 什么是 redo log?
        • redo log要写入磁盘,数据也要写磁盘,为什么要多此一举?
        • redo log什么时候刷盘
      • Redo Log和Undo Log的区别在哪?

前言

整理回顾MySQL的核心内容,后面每天会抽时间更新整理。
内容来自各个博客和书籍整理而来。

什么是事务

事务就是由单独单元的一个或多个SQL语句组成,在这个单元中,每个SQL语句都是相互依赖,而整个单独单元是不可分割的存在。
事务是一个整体,事务中的内容只能是都成功或者都不成功,不存在部分执行成功或者部分失败。

事务的特性

事务的特性内容简称ACID:

  • 原子性 Atomicity
    过程的保证
    事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做。
  • 一致性 consistency
    结果的保证
    事务执行的结果必需是使数据库从一个一致性状态变到另一个一致性状态。
    因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态,如果数据库系统运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。
  • 隔离性 Isolation
    防止并发事物相互干扰
    一个事物的执行不能被其他事物干扰。即一个事务内部的操作及使用的数据对其他并发事物是隔离的,并发执行的各个事务之间不能相互干扰。
  • 持久性 (永久性)Durability
    永久性保存
    一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其执行结果有任何影响。

InnoDB引擎通过什么技术来保证事务这四个特性呢?

  • 原子性通过 undo log(回滚日志)保证
  • 一致性通过持久性+原子性+隔离性来保证
  • 隔离性是通过MVCC(多版本并发控制)或锁机制保证
  • 持久性是通过redo log(重做日志)保证
    这些具体的日志,MVCC,锁在后面专辑内容里 我们都会介绍,这篇文章只谈涉及到的。

事务的状态

我们现在知道 事务 是一个抽象的概念,它其实对应着一个或多个数据库操作,MySQL根据这些操作所执
行的不同阶段把 事务 大致划分成几个状态:

  • 活动的(Active)
    事务对应的数据库操作正在执行过程中时,我们就说该事务处在活动的状态。
  • 部分提交的(Partially Committed)
    当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并没有刷新到磁盘时,我们就说该事务处在部分提交的状态。
  • 失败的(Failed)
    当事务处在活动的或者部分提交的状态时,可能遇到了某些错误(数据库自身的错误,操作系统或者直接断电等)而无法继续执行,或者人为的停止当前事务的执行,我们就说该事务处在失败的状态
  • 中止的(Aborted)
    如果事务执行了一部分而变为失败的状态,那么就需要把已经修改的事务中的操作还原到事务执行前的状态。
    换句话说,就说要撤销失败事务对当前数据库造成的影响。
    我们把这个撤销称为回滚。当回滚操作执行完毕时,也就是数据库恢复到了执行事务前的状态,我们就说事务处在了中止的状态。
  • 提交的(Committed)
    当一个处在部分提交的状态的事务将修改过的数据都同步到磁盘上之后,我们就可以说该事务处在了提交的状态。

状态转换图如下所示:
在这里插入图片描述

事务会引发什么问题?

MySQL服务端是允许多个客户端链接的,这意味着MySQL会出现同时处理多个事务的情况。
那么在处理多个事务,会出现以下几种问题:

  • 脏读(Dirty Read)
    一个事务在处理过程中读取了另外一个事务未提交的数据。
    当一个事务正在访问数据并且对其进行了修改,但是还没提交事务,这时另外一个事务也访问了这个数据,然后使用了这个数据,因为这个数据的修改还没提交到数据库,所以另外一个事务读取的数据就是“脏数据”,这种行为就是“脏读”,依据“脏数据”所做的操作可能是会出现这个问题。
    在这里插入图片描述

  • 修改丢失(Lost of Modify)
    是指一个事务读取一个数据时,另外一个数据也访问了该数据,那么在第一个事务修改了这个数据之后,第二个事务也修改了这个数据。
    这样第一个事务内的修改结果就被丢失。
    这个其实不会影响到程序的结果,只是逻辑上不正确。

  • 不可重复读(Unrepeatableread)
    指在一个事务内多次读取同一数据,在这个事务还没结束时,另外一个事务也访问了这个数据并对这个数据进行了修改,那么就可能造成第一个事务两次去读的数据不一致。
    在这里插入图片描述

  • 幻读(Phantom Read)
    指同一个事务内多次查询返回的结果集不一样(比如增加了或者减少了行记录)
    幻读与不可重复读类似,幻读是指一个事务读取了几行数据,这个事务还没结束,接着另外一个事务插入了一些数据,在随后的查询中,第一个事务读取的数据就会别原本读取的多,就像发生幻觉了一样。
    在这里插入图片描述
    总结一下:

  • 脏读:读到其他事物未提交的数据

  • 不可重复读:前后读取的数据不一致

  • 幻读:前后读取的记录数量不一致
    这三个现象的严重性排序如下:
    请添加图片描述
    那么如何解决上面的问题呢?

解决事物引发的问题手段

SQL标准提出了四种隔离级别来规避这些现象,隔离级别越高,性能越低,这四个隔离级别如下:

  • 读未提交:指一个事务还没提交,它做的变更就能被其他事物看到;
  • 读提交:指一个事务提交之后,它做的变更才能被其他事物看到;
  • 可重复读:指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB引擎的默认隔离级别;
  • 串行化:会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必需等前一个事务执行完成,才能继续执行。
    按隔离水平高低排序如下:
    在这里插入图片描述
    针对不同的隔离级别,并发事物时可能发生的现象也会不同:
    在这里插入图片描述
    那么这四种隔离级别具体是如何实现的呢?

事务日志

我们知道了事务有四种特性:原子性,一致性,隔离性和持久性。
事务的原子性,一致性和持久性可以由事务日志实现,我们下面具体来看一看。
日志大概分为三种:

  • undo log(回滚日志):是InnoDB存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和MVCC。
  • redo log‘(重做日志):是InnoDB存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障回复
  • binlog(归档日志):是Server层生成的日志,主要用于数据备份和主从赋值。
    注意,undo log是逻辑日志,对事物回滚时,只是将数据库逻辑地恢复到原来的样子。
    redo log是物理日志,记录的是数据页的物理变化,undo log不是redo log的逆过程。

Undo Log 日志

简单介绍

我们在执行执行一条“增删改”语句的时候,虽然没有输入 begin 开启事务和 commit 提交事务,但是 MySQL 会隐式开启事务来执行“增删改”语句的,执行完就自动提交事务的,这样就保证了执行完“增删改”语句后,我们可以及时在数据库表看到“增删改”的结果了。
是否开启自动提交事务,是由autocommit参数决定的,默认是开启。
有个问题需要考虑一下:
一个事务执行过程中,在还没有提交事务之前,如果MySQL发生了崩溃,要怎么回滚到事务之前的数据呢?

答案:我们在事务在执行过程中,都记录下回滚需要的信息到一个日志里,那么事务执行中途发生了MySQL崩溃后,就不需要担心无法回滚到事务之前的数据,我们可以通过这个日志回滚到事务之前的数据。

实现这一机制就是 Undo log(回滚日志),它保证了事务的ACID特性中的原子性(Atomicity)。

undo log 是一种用于撤销回退的日志。在事务没提交之前,MySQL会先记录更新前的数据到Undo log日志文件里面,当事务回滚时,可以利用undo log 来记录回滚,如下图:
在这里插入图片描述
每当InnoDB引擎对一条记录进行操作(新增,修改,删除)时,就把回滚时需要的信息都记录到undo log里,比如:

  • 在插入一条记录时
    要把这条记录的主键值记下来,这样之后回滚时只需要把这个主键值对应的记录删掉就好了;
  • 在删除一条记录时
    要把这条记录中的内容都记下来,这样之后回滚时再把由这些内容组成的记录插入到表中就好了;
  • 在更新一条记录时
    要把被更新的列的旧值记下来,这样之后回滚时再把这些列更新为旧值就好了。

在发生回滚时,就读取undo log里的数据,然后做原先相反的操作。

具体实现

不同的操作,需要记录的内容也是不同的,所以不同类型的操作产生的undo
log格式也不同,具体每个操作产生的undo log格式就不详细介绍了,感兴趣自己去查查吧。

一个记录的每一次更新操作产生的undo log格式都有一个roll_pointer指针和一个trx_id事务id:

  • 通过trx_id可以知道该记录被哪个事务修改的;
  • 通过roll_pointer指针可以将这些undo log串成一个链表,这个链表就称为版本链,如下图:
    在这里插入图片描述
    另外,undo log还有一个作用,通过ReadView+undo log 实现MVCC(多版本并发控制)。

对于【读提交】和【可重复读】隔离级别,他们快照读(普通select语句)是通过ReadView+undo log来实现的,它们的区别在于创建Read View的时机不同:

  • 【读提交】隔离级别是在每个select都会生成一个新的Read View,事务期间多次读取同一条数据,前后两次读的数据可能会出现不一致,因为这期间可能另外一个事务修改了该记录,并提交了事务。
  • 【可重复读】隔离级别是启动事务时生成了一个Read View,然后整个事务期间都在用这个Read View,这样就保证了在事务期间读到的数据都是事务启动前的记录。

这两个级别实现通过【事务的Read View里的字段】和【记录中的两个隐藏列(trx_id和roll_pointer指针)】的比对,如果不满足可见行,就会顺着undo log版本链里找到满足其可见性的记录,从而控制并发事物访问同一个记录时的行为,这就叫MVCC(多版本并发控制),

因此 undo log两大作用:

  • 实现事务回滚,保障事务的原子性。
    事务处理过程中,如果出现了错误或者用户执行了ROLLBACK语句,MYSQL可以易用undo log中的历史数据将数据恢复到事务开始之前的状态。
  • 实现MVCC(多版本并发控制)关键因素之一。
    MVCC是通过ReadView+undo log实现的。
    undo log为每条记录保存多份历史数据,MySQL在执行快照读(普通select语句)的时候,会根据事物的Read View里的信息,顺着undo log 的版本链找到满足其可见性的记录。

Buffer Pool

MySQL的数据都是存在磁盘中,那么我们要更新一条记录时,得先要从磁盘读取记录,然后在内存中修改这条记录。那修改完这条记录是选择直接写回磁盘,还是选择缓存起来呢?

当然是缓存起来好,这样下次有查询语句命中管理这条记录,直接读取缓存中的记录,就不需要从磁盘获取数据了。

为此InnoDB存储引擎设计了一个缓冲池(Buffer Pool),来提高数据库的读写性能。
在这里插入图片描述
有了Buffer Pool之后:

  • 读取数据时
    如果数据存在Buffer Pool中,客户端就会直接读取Buffer Pool中的数据,否则再去磁盘中读取。
  • 修改数据时
    如果数据存在Buffer Pool中,那直接修改Buffer Pool中数据所在的页,然后将其页设置为脏页(该页的内存数据和磁盘上的数据已经不一致),为了减少磁盘I/O,不会立即将脏页写入磁盘,后续由后台线程选择合适时机将脏页写入磁盘。
Buffer Pool缓存什么?

InnoDB会把存储的数据划分为若干个【页】,以页作为磁盘和内存交互的基本单位,一个页的默认大小为16KB,因此,Buffer Pool同样按照【页】来划分。
在 MySQL 启动的时候,InnoDB 会为 Buffer Pool 申请一片连续的内存空间,然后按照默认的16KB的大小划分出一个个的页, Buffer Pool 中的页就叫做缓存页。此时这些缓存页都是空闲的,之后随着程序的运行,才会有磁盘上的页被缓存到 Buffer Pool 中。

所以,MySQL 刚启动的时候,你会观察到使用的虚拟内存空间很大,而使用到的物理内存空间却很小,这是因为只有这些虚拟内存被访问后,操作系统才会触发缺页中断,申请物理内存,接着将虚拟地址和物理地址建立映射关系。

Buffer Pool 除了缓存「索引页」和「数据页」,还包括了 Undo 页,插入缓存、自适应哈希索引、锁信息等等。
在这里插入图片描述
注意:并不是查询一条记录,就只缓冲一条记录的。
InnoDB会把整个页的数据加载到Buffer Pool中,将页加载到Buffer Pool

Redo Log日志

为什么需要Redo Log?

我们知道了Buffer Pool是提高了读写效率,但是问题来了,Buffer Pool是基于内存的,而内存是不可靠的,万一断点重启,还没来得及落盘的脏页数据就会丢失。
为了防止断电导致数据丢失的问题,当有一条记录需要更新时,InnoDB引擎就会先更新内存(同时标记为脏页),然后将本次对这个页的修改以redo log的形式记录下来,这个时候更新就算完成了。
后续,InnoDB引擎在适当的时候,由后台线程将缓存在Buffer Poll的脏页刷新到磁盘里,这就是WAL(Write-Ahead Logging)技术
WAL技术指的是:MySQL的写操作并不是立刻写到磁盘上,而是先写日志,然后在合适的时间再写到磁盘上。
过程如下:
在这里插入图片描述

什么是 redo log?

redo log 是物理日志,记录了某个数据页做了什么修改(比如对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新),每当执行一个事务就会产生这样的一条或者多条物理日志。

在事务提交时,只要先将 redo log持久化到磁盘即可,可以不需要等到缓存在Buffer Pool里的脏页数据持久化到磁盘。

当系统崩溃时,虽然脏页数据没有持久化,但是redo log已经持久化,接着MySQL重启后,根据redo log的内容,将所有数据恢复到最新的状态。

注意:被修改undo log时,需要记录对应的redo log
开始事务后,InnoDB层更新记录前,首先要记录相应的undo log,如果是更新操作,需要把更新的列的旧值记下来,也就是要生成一条undo log,undo log会写入Buffer Pool中的Undo页面。
不过在内存修改undo log页面后,需要记录对应的redo log。

redo log要写入磁盘,数据也要写磁盘,为什么要多此一举?

写入redo log的方式使用了追加操作,所以磁盘操作是顺序写,而写入数据需要先找到写入位置,然后才写到磁盘,所以磁盘操作是随机写

磁盘的顺序写比随机写高效的多,因此redo log写入磁盘的开销更小。

针对顺序写为什么比随机写更快这个问题(举个例子,你有一个本子)

redo log什么时候刷盘

Redo Log和Undo Log的区别在哪?

这两种日志都属于InnoDB存储引擎的日志,它们的区别在于:

  • redo log记录了此次事务【完成后】的数据状态,记录的是更新之后的值;
  • undo log记录了此次事务【开始前】的数据状态,记录的是更新之前的值;
    事务提交之前发生了崩溃,重启后会通过undo log回滚事务,事务提交之后发生了崩溃,重启后会通过redo log恢复事务,如下图:
    在这里插入图片描述
    所以有了redo log,再通过WAL技术,InnoDB就可以保证即使数据库发生异常重启,之前已提交的记录都不会丢失,这个能力称为crash-safe(崩溃恢复),

后面内容待更新,近期补上,上面的内容细节也会补上。

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

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

相关文章

保姆级教程:手把手教你使用 Keras 搭建神经网络

大家好,本文从0到1详细讲解两种基于Keras的建模方法: 基于Sequential的建模;快速方便,易上手 基于函数式API的建模;易于扩展,灵活性强 文章目录你会学到什么?技术提升导入内置数据集数据缩放和…

【GRU回归预测】基于卷积神经网络结合门控循环单元CNN-GRU实现数据多维输入单输出预测附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

ChatGPT强悍的编程能力,让我吓出一身冷汗!

最近有好几个人给我安利ChatGPT,说老刘快你去看看吧,这货实在太强了,搞不好我们程序员都失业了。刚开始我都是微微一笑,怎么可能?我之前的观点一直都是在我的有生之年,AI绝对不可能干掉程序员。但是安利的人…

一篇文章让你懂 io流

文件:就是保存数据的地方。文件流:文件在程序中是以流的形式来操作的。流:数据在数据源(文件)和程序(内存)之间经历的路径。输入流:数据从文件(磁盘)到Java程…

Spring-Cloud-Admin-06

前言 admin是用来监控各个服务的状况的,通过前台页面,可以查看我们各个服务的一个状态,是否在线,服务状况的一个框架。 服务端项目使用 admin有服务端和客户端,我们不需要每个服务都导入admin的客户端依赖,…

以太网 网络高可用性(链路聚合、LACP模式、静态手动模式)

2.9.0 以太网 网络高可用性(链路聚合、LACP模式、静态手动模式) 网络高可用性2.9.0 以太网 网络高可用性(链路聚合、LACP模式、静态手动模式)一、简介:1、单板可靠性:1.1、实现机柜式的可靠性提升&#xff…

Java#35(多线程扩展)

目录 一.定时器 定时器是一种控制任务延时调用, 或者周期调用的技术 1.Timer定时器(不推荐) 2.ScheduledExecutorService定时器(推荐) 二.并发与并行 三.线程状态 一.定时器 定时器是一种控制任务延时调用, 或者周期调用的技术 1.Timer定时器(不推荐) 代码示范: import …

Microsoft Store无法打开的解决办法【成功解决】

Microsoft Store无法打开解决办法我自己的解决办法其他Bug导致Microsoft Store无法打开的解决办法vpn代理问题使用TLS 1.2其他BUG解决方案成功解决之前我就有安装wsl的想法,但是他要求打开Microsoft Store,我尝试了各种办法,都不行。今天终于…

SpringCloud-全面详解(学习总结---从入门到深化)

​​​​​​​ 微服务架构进化论 单体应用阶段 (夫妻摊位) 在互联网发展的初期,用户数量少,一般网站的流量也很少,但硬 件成本较高。因此,一般的企业会将所有的功能都集成在一起开发 一个单体应用,然后将该单体应用…

Python代码加速100倍,针对Excel自动化处理的加速实战!

并发 vs 并行 说到并发编程,我们先来澄清一下并发 (Concurrency) 和 并行 ( Parallelism)这两个概念,因为这个两个概念的含义是不同的。 并行(Parallelism)指的就是在同一时刻,有两个或两个以上的任务的代码在处理器…

Spring Cloud Ribbon(负载均衡器)介绍及使用

目前主流的负载方案分为以下两种: 集中式负载均衡,在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx)。客户端自己做负载均衡&#x…

[附源码]Python计算机毕业设计SSM基于框架的秧苗以及农产品交易网站(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

命令设计模式

一、命令模式 1、定义 命令模式(Command Pattern)是对命令的封装,每一个命令都是一个操作,请求方发出请求要求执行一个操作,接收方收到请求并执行操作。属于行为型设计模式。 命令模式通过在请求与实现之间引入一个抽…

Spring注解开发

1、Spring注解开发 1 注解开发定义Bean对象【重点】 目的:xml配置Bean对象有些繁琐,使用注解简化Bean对象的定义 问题导入 问题1:使用什么标签进行Spring注解包扫描? 问题2:Component注解和Controller、Service、Re…

【指纹识别】指纹识别【含GUI Matlab源码 029期】

⛄一、指纹识别简介 指纹识别技术主要分三个步骤:指纹预处理、特征提取、指纹分类与匹配。 无论是指纹分类还是指纹匹配,都需要提取指纹的有效特征,而特征提取的性能很大程度上要依赖于指纹图像的质量。在实际应用中,由于采集条件和采集设备的因素,采集到的指纹图像…

IBRNet:基于IBR的NeRF

IBRNet: Learning Multi-View Image-Based Rendering 针对问题:使NeRF具有泛化能力 如何做:主要还是针对颜色和密度的预测进行改进(三维重建部分),和NeRF一样,使用的是volume rendering(渲染部…

Vulkan下多线程渲染设计

1 Vulkan 视角下的多线程渲染 首先我们需要从vulkan api的顶层框架上来看一下,它在哪些地方可以让我们并行。 Vulkan API的基本框架 Vulkan不同于Gles只有一个(不被API暴露出来的)单一链条的cmdbuffer处理,它最大的特点是允许多…

阿里巴巴内部:2022年全技术栈PPT分享(架构篇+算法篇+大数据)

我只截图不说话,PPT大全,氛围研发篇、算法篇、大数据、Java后端架构!除了大家熟悉的交易、支付场景外,支撑起阿里双十一交易1682亿元的“超级工程”其实包括以下但不限于客服、搜索、推荐、广告、库存、物流、云计算等。 Java核心…

Linux中裸机串口通信的基本方法

大家好, 今天主要和大家聊一聊,如何使用串口进行通信的方法。 目录 第一:串口的基本简介 第二:UART的特点 ​第三:UART的配置步骤 第一:串口的基本简介 串口又叫做串行接口,通常叫做COM接…

农业灌区量测水流量在线监测系统解决方案-灌区信息化管理系统-灌区水网智慧化

平升电子农业灌区量测水流量在线监测系统解决方案/灌区信息化管理系统/灌区水网智慧化,对灌区的渠道水位、流量、水雨情、土壤墒情、气象等信息进行监测,同时对泵站、闸门进行远程控制,对重点区域进行视频监控,实现了信息的采集、…