面试笔记——MySQL(事务:事务特性、并发事务、事务隔离、Redo Log与Undo Log、MVCC)

事务

概念与特性

事务(Transaction)指的是一组数据库操作,这些操作要么全部成功执行,要么全部不执行,保证了数据库的一致性和完整性,它使得数据库操作可以按照逻辑上的单元进行组织和执行,提高了数据的可靠性和可维护性。事务通常具有以下四个特性,通常被称为ACID属性:

  1. 原子性(Atomicity):事务中的所有操作要么全部执行成功,要么全部不执行,即事务是一个不可分割的最小执行单元。如果事务中的任何一部分操作失败,整个事务都将被回滚(Rollback),数据库状态将会恢复到事务开始前的状态,保持数据的一致性。

  2. 一致性(Consistency):事务执行的结果必须使数据库从一个一致性状态转变到另一个一致性状态。这意味着事务必须满足数据库的约束和规则,如唯一性约束、外键约束等。

  3. 隔离性(Isolation):多个事务同时并发执行时,每个事务都应该被隔离开来,互相不受影响。即使有多个事务同时修改同一数据,它们之间也不能相互干扰,每个事务应该感知不到其他事务的存在。

  4. 持久性(Durability):一旦事务提交(Commit),其所做的修改将会永久保存在数据库中,即使系统发生故障,数据也不会丢失。数据库系统通常通过将事务日志写入持久存储介质(如磁盘)来实现持久性。

并发事务

并发事务可能引发的问题:脏读、不可重复读、幻读
通过隔离级别解决上述问题:读未提交、读已提交、可重复读、串行化

问题描述
脏读一个事务读到另外一个事务还没有提交的数据。
不可重复读在一个事务中,同一查询多次执行却得到了不同的结果。
幻读在一个事务中,同一查询多次执行却得到了不同数量的结果。

脏读
假设有两个事务,事务 A 读取了事务 B 修改但尚未提交的数据,然后事务 B 回滚了修改,那么事务 A 所读取的数据就是不正确的,因为它读取到了未提交的、“脏”的数据。脏读可能导致读取到不一致的数据,降低了数据的可靠性。
在这里插入图片描述
不可重复读
假设事务 A 在执行查询时读取了某一行数据,然后事务 B 修改了这行数据并提交了事务,之后事务 A 再次执行相同的查询,此时得到的数据就可能与之前不同,导致了不一致的读取结果。这种情况下,事务 A 的读操作就发生了不可重复读。不可重复读可能破坏了事务的隔离性。
在这里插入图片描述
幻读
假设事务 A 在执行一个范围查询时,得到了一些行,然后事务 B 在执行 INSERT 或 DELETE 操作,导致事务 A 再次执行相同的查询时得到了不同的行数,就发生了幻读。幻读可能会导致在同一事务中看到不一致的数据,破坏了事务的隔离性。

还有一种情况——在解决了不可重复读问题的背景下,事务A想要在数据库中添加id为1的数据,首先它会查询是否存在id为1的数据,此时的查询结果是没有;在事务A进行插入操作之前,事务B向数据库中插入了id为1的数据并提交;当事务A再进行插入操作时,就会报错;事务A再次查询数据,但查询结果和第一次查询一致(表示没有该数据),此时就出现了幻读:
在这里插入图片描述

假设有一个银行账户表,其中有两个账户:账户A和账户B。

  1. 脏读:假设账户A的余额为1000元,事务A读取了账户A的余额,此时账户A的余额为1000元。然后事务B修改了账户A的余额为2000元,但尚未提交。此时,事务A再次读取账户A的余额,就会读到未提交的“脏”数据2000元,而实际上账户A的余额还是1000元。

  2. 不可重复读:假设事务A读取了账户A的余额为1000元,然后事务B将账户A的余额修改为2000元并提交。接着,事务A再次读取账户A的余额,此时读取到的余额为2000元,与之前的结果不同。

  3. 幻读:假设事务A执行了一个范围查询,查询所有余额大于1000元的账户,此时得到了账户A和账户B两个结果。然后事务B插入了一笔新的账户记录,使得账户C的余额也大于1000元。接着,事务A再次执行相同的查询,却得到了账户A、账户B和账户C三个结果,出现了幻读现象。

事务隔离

隔离级别脏读不可重复读幻读
Read uncommitted 未提交读
Read committed 读已提交×
Repeatable Read(MySQL默认) 可重复读××
Serializable 串行化×××

注意:事务隔离级别越高(上表中,隔离级别有上到下依次增高),数据越安全,但是性能越低。MySQL默认隔离级别是可重复读

Redo Log与Undo Log

缓冲池(buffer pool):是主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),以一定频率刷新到磁盘,从而减少磁盘IO,加快处理速度。
数据页(page):是InnoDB 存储引擎磁盘管理的最小单元,每个页的大小默认为 16KB。页中存储的是行数据。
图1:
在这里插入图片描述
当我们操作数据的时候(如上图中的update,delete语句),并不是直接操作磁盘,而是首先去操作内存(缓冲池)。当一个操作被提交后,会先查询缓冲池中是否存在需要操作的数据。若没有,则从磁盘中将数据加载到内存(将数据所在的某页数据存储在缓冲池)。当缓冲池中有数据,则在操作完数据之后,按一定的频率将缓冲池的数据同步到磁盘中。以此减少磁盘的I/O,加快处理速度。

以上方法虽然提高了效率,但也存在一些问题。例如,当操作完数据后,缓冲区里面的已有新的数据页,但还并未同步到磁盘中,此时缓冲区里面的数据页称为脏页。若数据还未完成同步,而服务器发生宕机,那么内存中的数据就会丢失,已经操作完成的数据(在缓存中)也会丢失,因此违背了事务的持久化的特性。

Redo Log(重做日志):记录的是事务提交时数据页的物理修改,是用来实现事务的持久性
该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中, 用于在刷新脏页到磁盘,发生错误时, 进行数据恢复使用。
图2:
在这里插入图片描述
当进行数据操作时,缓冲池中的数据发生了变化,同时Redo Log buffer 中会记录这些数据页的变化,一旦Redo Log buffer 中发生变化,就会同步把这些数据记录到磁盘文件中。若对脏页中的数据进行同步失败时,就会从Redo Log中同步数据。

ps:在磁盘中,Redo log file实际有两份,他们是循环写的。有两份Redo log file的原因:

  1. 容错和可靠性:有两份Redo Log文件可以提高数据库的容错能力。如果一份Redo Log文件发生损坏或丢失,数据库可以继续正常运行并使用另一份Redo Log文件来进行恢复。这样可以避免因为单点故障导致的数据丢失或数据库无法启动等问题。

  2. 性能和并发:两份Redo Log文件可以提高并发性能。MySQL的Redo Log是循环写入的,当一个Redo Log文件写满时,数据库会切换到另一份Redo Log文件,这样可以避免写操作的阻塞,提高了并发处理能力。

  3. 恢复速度:当数据库需要进行恢复操作时,拥有两份Redo Log文件可以加快恢复的速度。数据库可以同时使用两份Redo Log文件进行恢复操作,从而加快了恢复的速度,减少了系统 downtime。

关于通过日志同步数据(图2),而不是采用直接同步数据(图1)的问题?
因为操作数据的时候,可能有多条记录(包含大量的操作)。而将数据同步到磁盘的时候,都是随机磁盘I/O,因此同步数据的性能是非常低的。如果使用Redo Log,在进行日志文件同步的时候是顺序磁盘I/O(因为日志文件是以追加的形式添加的数据),因此同步日志文件的性能会提升很多。所以,采用Redo Log方式同步。这种方式也称为WAL。

这部分可与Redis中的双写一致性联系https://blog.csdn.net/Z__XY_/article/details/136820674?spm=1001.2014.3001.5501。

补充:

  1. 随机磁盘I/O

    • 随机磁盘I/O指的是对磁盘上的数据进行随机的读取或写入操作,即访问不连续的数据块。
    • 随机磁盘I/O的特点是磁盘臂需要频繁地移动,寻找数据所在的位置,因此会导致磁盘的寻道时间增加,I/O性能相对较低。
  2. 顺序磁盘I/O

    • 顺序磁盘I/O指的是对磁盘上的数据进行顺序的读取或写入操作,即按照数据在磁盘上的物理顺序进行访问。
    • 顺序磁盘I/O的特点是磁盘臂不需要频繁移动,可以顺序地读取连续的数据块,因此具有较高的I/O性能,能够充分利用磁盘的吞吐能力。

Undo Log(回滚日志): 用于记录数据被修改前的信息 , 作用包含两个 : 提供回滚 和 MVCC(多版本并发控制) 。undo log和redo log记录物理日志不一样,它是逻辑日志,它保证了事务的原子性和一致性

  • 可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,
  • 当update一条记录时,它记录一条对应相反的update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

Undo Log与Redo Log的区别总结如下:

  • Undo日志记录了事务对数据库的修改操作的逆操作(记录的是逻辑日志),用于回滚操作和MVCC,保证事务的原子性和一致性
  • Redo日志记录了事务对数据库的修改操作的正向操作(记录的是数据页的物理变化),用于恢复数据库的持久性,保证事务的持久性
  • Undo日志记录旧值,Redo日志记录新值。
  • Undo日志的主要目的是回滚,而Redo日志的主要目的是恢复。
  • Undo日志通常与事务数据绑定,Redo日志通常是独立的。
MVCC

MVCC(Multi-Version Concurrency Control,多版本并发控制),指维护一个数据的多个版本,使得读写操作没有冲突。当一个事务执行写操作时,数据库系统会为其创建一个新版本,并将该版本标记为最新版本。其他事务仍然可以读取旧版本的数据,直到该版本被清除或过期。
MVCC的具体实现,主要依赖于数据库记录中的3个隐式字段、undo log、readView。

隐藏字段
如图:
在这里插入图片描述

隐藏字段含义
DB_TRX_ID最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。
DB_ROLL_PTR回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。
DB_ROW_ID隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。

undo log

  • 回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志。
  • 当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除。
  • 而update、delete的时候,产生的undo log日志不仅在回滚时需要,mvcc版本访问也需要,不会立即被删除。

undo log版本链:
不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录。
如图1——事务2对数据进行修改:
在这里插入图片描述
然后,事务3又对同一个数据进行修改:
在这里插入图片描述

随后,事务4对同一数据进行修改:
在这里插入图片描述
此时得到一个undo log版本链。

Readview
ReadView(读视图)是 快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。

  • 当前读

    • 读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select … lock in share mode(共享锁),select … for update、update、insert、delete(排他锁)都是一种当前读。
    • 如下图,事务A分别使用操作1和操作3查询id为1的数据,事务B在事务A执行操作1、3之间进行了数据修改操作,那么事务A在操作3拿到的是修改后的最新数据:
      在这里插入图片描述
  • 快照读

    • 简单的select(不加锁)就是快照读,快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。
    • Read Committed:每次select,都生成一个快照读,即,每次读到的都是最细数据。
    • Repeatable Read:开启事务后第一个select语句才是快照读的地方,解决了可重复读的问题。

ReadView维护的事务包含了一下四个核心字段:
在这里插入图片描述
下图中展示了4个事务在不同时刻的操作:
在这里插入图片描述
如果在事务5的sql语句——“查询id为30的记录”时刻,此时readview中记录核心字段的组成——m_ids:事务3、4和5(事务2在此刻之前已经提交了事务);min_trx_id:事务3;max_trx_id:事务6(当前最大事务是5);creator_trx_id:事务5(因为在该事务中进行的查询操作,说明在该事务中创建的readview)。

readview为了能够在快照读中读取最准确的数据,定义了以下规则(还是用上面的事务5作为创建事务id为例):
在这里插入图片描述

  • 针对①,说明事务5 可以访问 自己更改的数据;
  • 针对②,当前最小的活跃事务id是事务3,比事务3小的事务id则是事务2,说明该事务已经提交了,则事务5也能访问事务2修改的数据;
  • 针对③,事务5的id小于事务6,则说明 不能访问 事务6更改后的数据;
  • 针对④,判断事务id 大于等于最小活跃事务id,且小于等于预分配事务id,且不在m_ids中,这表示事务5能已提交的事务修改后的数据。(举例:若事务4在事务5的第一条查询语句之前完成事务提交,则说明事务5可以访问事务4修改后的数据。)

不同的隔离级别,生成ReadView的时机不同:

  • READ COMMITTED :在事务中每一次执行快照读时生成ReadView。
  • REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。

RC隔离级别下,在事务中每一次执行快照读时生成ReadView。 如图:
在这里插入图片描述
事务5在第一次查询时,可以访问事务2更改后的数据(从上到下依次将事务id带入版本链数据访问规则进行判断,如——针对事务4:①事务4不等于事务5;②事务4大于最小活跃事务(事务id为3);③事务4<小于预分配事务id(id为6);④事务4虽在最小活跃事务id和预分配事务id范围内,但它同时数据m_ids,因此不能访问事务4。其他事务按相同的方式判断):
在这里插入图片描述

事务5在第二次查询,可以访问事务3更改后的数据:
在这里插入图片描述

RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。 如图:
在这里插入图片描述

MVCC机制的优点包括:

  • 提高了并发性:多个事务可以同时读取和修改数据库,而不会相互阻塞,提高了数据库的并发处理能力。
  • 避免了读写冲突:通过使用快照读和版本控制,MVCC可以避免读写冲突,提高了系统的稳定性和可靠性。
  • 支持一致性读取:MVCC保证了读取操作可以读取到一致性的数据快照,即使在并发写入的情况下也能保持一致性。

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

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

相关文章

视频号小店入口在哪?怎么运营?全流程分享!

我是电商珠珠 视频号小店是视频号在22年7月宣布的电商平台&#xff0c;是供商家做店所使用。到现在也发展了不过一年的时间&#xff0c;所以有很多商家都想要往这个平台上转&#xff0c;其中包括新手。因为这个平台属于初期&#xff0c;所以红利比较大&#xff0c;规则限制没有…

CDMP认证是一个什么样的证书?有必要参加CDMP培训吗?通过率高不高?

在当前数字化时代&#xff0c;数据管理变得愈发重要。为了满足社会对数据管理人才的紧迫需求&#xff0c;DAMA国际于2004年推出了CDMP数据管理专业认证。这是一项综合资格认证&#xff0c;涵盖学历教育、工作经验和专业知识考试。CDMP认证是全球唯一的数据管理方面权威性认证&a…

[Rust] 使用vscode实现HelloWorld程序并进行debug

一、简介 本文介绍了如何使用vscode编写rust&#xff0c;实现打印"Hello, world!"的程序。 二、工具安装 0. 环境介绍&#xff1a; Linux &#xff08;或者windowswsl&#xff09; 1. 安装rust编译器rustc和包管理器cargo。 请参考连接&#xff1a;Rust 程序设…

wy的leetcode刷题记录_Day92

wy的leetcode刷题记录_Day92 声明 本文章的所有题目信息都来源于leetcode 如有侵权请联系我删掉! 时间&#xff1a;2024-3-22 前言 目录 wy的leetcode刷题记录_Day92声明前言2617. 网格图中最少访问的格子数题目介绍思路代码收获 695. 岛屿的最大面积题目介绍思路代码收获 2…

java网络原理(二)------TCP确认应答和超时重传

一Tcp协议 TCP&#xff0c;即Transmission Control Protocol&#xff0c;传输控制协议。人如其名&#xff0c;要对数据的传输进行一个详细的控制。 二.TCP协议段格式 知道了端口号才能进一步确认这个数据报交给了哪一个程序。16为端口号是2字节&#xff0c;范围是0到65535.如…

牛,The O-one ——通过语音交互控制电脑的开源语言模型

模型介绍 The O-one &#xff1a;一个创新的开源语言模型计算机 可以让你通过语音交互来和你的计算机进行对话&#xff0c;完成询问、指令下达等任务。灵感居然来自Andrej Karpathy 的 LLM 操作系统。O1运行一个代码解释语言模型&#xff0c;并在计算机内核发生特定事件时调用…

音视频开发_FFmpeg基石精讲

FFmpeg 框架 核心组件 libavcodec&#xff1a;一个编解码库&#xff0c;包含了众多的编码器和解码器用于编码和解码音视频流。libavformat&#xff1a;一个封装格式库&#xff0c;用于处理各种音视频封装格式。libavutil&#xff1a;一个工具库&#xff0c;提供了常见功能的简…

交互式QGraphicsView(平移/缩放/旋转)

一 简述 Graphics View提供了一个平台&#xff0c;用于大量自定义 2D 图元的管理与交互&#xff0c;框架包括一个事件传播架构&#xff0c;支持场景 Scene 中的图元 Item 进行精确的双精度交互功能。Item 可以处理键盘事件、鼠标按下、移动、释放和双击事件&#xff0c;同时也…

SAP-MM-设置字段默认值

当我们创建订单时&#xff0c;有些字段总是重复输入&#xff0c;每次值也是固定的&#xff0c;例如生产订单 如上图“生产工厂都是1000”如何设置成默认每次进入都是1000呢&#xff1f; 点击字段&#xff0c;F1 查看参数ID“WRK” 输入tcode&#xff1a;SU3 按上图维护数据100…

Quartz完全开发手册(一篇学会Quartz所有知识点)

目录 一、Quartz概念 1.1、Quartz介绍 1.2、使用场景 1.3、特点 二、Quartz运行环境 三、Quartz设计模式 四、Quartz学习的核心概念 4.1、任务Job 4.2、触发器Trigger 4.3、调度器Scheduler 五、Quartz的体系结构与工作流程 5.1、体系结构 5.2、工作流程 六、Quar…

Python Flask框架 -- 模版继承

一个网站中&#xff0c;大部分网页的模块是重复的&#xff0c;比如顶部的导航栏&#xff0c;底部的备案信息。如果在每个页面中都重复的去写这些代码&#xff0c;会让项目变得臃肿&#xff0c;提高后期维护成本。比较好的做法是&#xff0c;通过模板继承&#xff0c;把一些重复…

SpringBoot-04 | spring-boot-starter-logging原理原理

SpringBoot-04 | spring-boot-starter-logging原理原理 第一步&#xff1a;springboot加载factories文件第二步&#xff1a;构造监听器第三步&#xff1a;注册监听器到Spring中第四步&#xff1a;开始加载日志框架第五步&#xff1a;加载日志框架logback-spring.xml第六步&…

全域电商数据实现高效稳定大批量采集♀

全域电商&#xff0c;是近几年的新趋势&#xff0c;几乎所有商家都在布局全域&#xff0c;追求全域增长。但商家发现&#xff0c;随着投入成本的上涨&#xff0c;利润却没有增加。 其中最为突出的是——商家为保证全域数据的及时更新&#xff0c;通过堆人头的方式完成每日取数任…

【应用笔记】LAT1305+使用STM32+TT类型IO的注意事项

1. 概述 在 STM32 系列 MCU 中&#xff0c; 除了一些特殊管脚外&#xff0c;绝大多数管脚都可以分类为 FT (兼容5V 信号)或 TT&#xff08;兼容 3V3 信号&#xff09;类型的 IO&#xff0c;由于 MCU 内部设计的不同&#xff0c; TT IO 相比 5V IO 有更多的限制&#xff0c;下面…

I2C协议

一.硬件连接 I2C必须使用开漏&#xff08;或集电极开路&#xff09;的引脚&#xff0c;其引脚框图如下所示。 SCL0对应78K0的P6.0引脚&#xff0c;SDA0对应78K0的P6.1引脚。 在使用开漏引脚通信时&#xff0c;需注意如下事项&#xff1a; 1&#xff09;两条总线须外接…

国产之光?Kimichat大模型200万字超长上下文突破

Kimi Chat简介 Kimi是AI大模型初创企业月之暗面&#xff08;Moonshot&#xff09;推出的AI产品。近日月之暗面宣布Kimi 智能助手在长上下文窗口技术上再次取得突破&#xff0c;无损上下文长度提升了一个数量级到200万字。 月之暗面&#xff08;Moonshot AI&#xff09;&#…

保姆级系列教程-玩转Fiddler抓包教程(1)-HTTP和HTTPS基础知识

2024软件测试面试刷题&#xff0c;这个小程序&#xff08;永久刷题&#xff09;&#xff0c;靠它快速找到工作了&#xff01;&#xff08;刷题APP的天花板&#xff09;【持续更新最新版】-CSDN博客 1.简介 有的小伙伴或者童鞋们可能会好奇地问&#xff0c;不是讲解和分享抓包…

CI/CD实战-jenkins部署 3

安装 软件下载地址&#xff1a;Index of /jenkins/redhat/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 启动服务 安装推荐插件 不新建用户&#xff0c;使用admin账号登录 修改一下初始密码 新建项目测试 安装git命令 生成密钥 在gitlab中上传公钥 修改ssh 创建中…

babel主要内容

定义 babel是一个编译工具 &#xff0c;用于把JSX等编译成浏览器可执行的javascript。 主要内容是几个包babel/parser 这个包主要是用于解析代码到AST树babel/types 这个包中有一堆API&#xff0c;用于手动创建ASTbabel/traverse 这个包主要是为了遍历AST树&#xff0c;结合具体…

C/C++代码性能优化——编程实践

1. 编程实践 在一些关键的地方&#xff0c;相应的编程技巧能够给性能带来重大提升。 1.1. 参数传递 传递非基本类型时&#xff0c;使用引用或指针&#xff0c;这样可以避免传递过程中发生拷贝。参数根据是否需要返回&#xff0c;相应加上const修饰&#xff0c;代码更安全&am…