面试官:请说一下Mysql事务实现原理
在日常工作中,数据库是我们必须使用的,其中使用最多的也是大部分中小公司的选择是Mysql,跳槽面试中也是必问的,今天我们就说一下Mysql事务
MySQL中的事务实现原理主要涉及以下几个方面:
- ACID特性:MySQL支持事务的原因之一是它遵循ACID(原子性、一致性、隔离性和持久性)特性。这意味着在一个事务中的所有操作要么全部成功地提交,要么全部失败回滚。这确保了数据的一致性和可靠性。
- 日志:MySQL使用日志来记录事务的操作和变化。MySQL有两种主要的日志类型:重做日志(Redo Log)和回滚日志(Undo Log)。
- 锁机制:MySQL使用锁机制来实现事务的隔离性,保证并发事务的正确执行。MySQL支持多种类型的锁,如共享锁(Shared Lock)和排他锁(Exclusive Lock),以及行级锁和表级锁等。锁机制可以防止多个事务同时修改同一个数据,保证数据的一致性。
- MVCC(多版本并发控制):MVCC是MySQL中的一种并发控制机制,用于在并发事务执行时保证数据的隔离性。MVCC通过在每个数据行上维护多个版本来实现。每个事务在读取数据时,会根据自己的事务ID和数据行的版本信息来确定可见的数据版本,从而实现不同事务之间的隔离性。
- 事务管理器:MySQL有一个事务管理器来协调和管理事务的执行。事务管理器负责事务的开始、提交、回滚和并发控制等。它还负责处理并发事务之间的冲突和死锁等问题。
综上所述,MySQL通过使用日志、锁机制、MVCC和事务管理器等技术来实现事务的原子性、一致性、隔离性和持久性。这些机制保证了数据的完整性和一致性,并提供了高并发的支持。
其中ACID四大特性,实际上分为两个部分,其中的原子性、一致性、持久性,实际上是由InnoDB中的两份日志来保证的,一份是redo log日志,一份是undo log日志。而隔离性是通过数据库的锁,加上MVCC来保证的。

我们在讲解事务原理的时候,主要就是来研究一下redolog,undolog以及MVCC
事务基础ACID
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
特性
• 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
• 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
• 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
• 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
那实际上,我们研究事务的原理,就是研究MySQL的InnoDB引擎是如何保证事务的这四大特性的。

redo log重做日志
记录的是事务提交时数据页的物理修改,是用来实现事务的持久性。
该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中, 用于在刷新脏页到磁盘,发生错误时, 进行数据恢复使用。
如果没有redolog,可能会存在什么问题的?我们一起来分析一下。我们知道,在InnoDB引擎中的内存结构中,主要的内存区域就是缓冲池,在缓冲池中缓存了很多的数据页。当我们在一个事务中,执行多个增删改的操作时,InnoDB引擎会先操作缓冲池中的数据,如果缓冲区没有对应的数据,会通过后台线程将磁盘中的数据加载出来,存放在缓冲区中,然后将缓冲池中的数据修改,修改后的数据页我们称为脏页。而脏页则会在一定的时机,通过后台线程刷新到磁盘中,从而保证缓冲区与磁盘的数据一致。而缓冲区的脏页数据并不是实时刷新的,而是一段时间之后将缓冲区的数据刷新到磁盘中,假如刷新到磁盘的过程出错了,而提示给用户事务提交成功,而数据却没有持久化下来,这就出现问题了,没有保证事务的持久性。

那么,如何解决上述的问题呢?在InnoDB中提供了一份日志 redo log,接下来我们再来分析一下,通过redolog如何解决这个问题。

有了redolog之后,当对缓冲区的数据进行增删改之后,会首先将操作的数据页的变化,记录在redo log buffer中。在事务提交时,会将redo log buffer中的数据刷新到redo log磁盘文件中。过一段时间之后,如果刷新缓冲区的脏页到磁盘时,发生错误,此时就可以借助于redo log进行数据恢复,这样就保证了事务的持久性。而如果脏页成功刷新到磁盘或或者涉及到的数据已经落盘,此时redolog就没有作用了,就可以删除了,所以存在的两个redolog文件是循环写的。那为什么每一次提交事务,要刷新redo log 到磁盘中呢,而不是直接将buffer pool中的脏页刷新到磁盘呢 ?
因为在业务操作中,我们操作数据一般都是随机读写磁盘的,而不是顺序读写磁盘。而redo log在往磁盘文件中写入数据,由于是日志文件,所以都是顺序写的。顺序写的效率,要远大于随机写。这种先写日志的方式,称之为 WAL(Write-Ahead Logging 预写日志)。
undo log回滚日志
用于记录数据被修改前的信息 , 作用包含两个 : 提供回滚(保证事务的原子性) 和MVCC(多版本并发控制
undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。
Undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC。
Undo log存储:undo log采用段的方式进行管理和记录,存放在前面介绍的 rollback segment 回滚段中,内部包含1024个undo log segment。
MVCC
全称 Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。
接下来介绍一下InnoDB引擎的表中涉及到的隐藏字段、undolog 以及 readview。
隐藏字段
当我们创建了上面的这张表,我们在查看表结构的时候,就可以显式的看到这三个字段。实际上除了这三个字段以外,InnoDB还会自动的给我们添加三个隐藏字段及其含义分别是:
| 隐藏字段 | 含义 |
|---|---|
| DB_TRX_ID | 最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。 |
| DB_ROLL_PTR | 回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。 |
| DB_ROW_ID | 隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。 |
而上述的前两个字段是肯定会添加的,是否添加最后一个字段DB_ROW_ID,得看当前表有没有主键,如果有主键,则不会添加该隐藏字段。
undolog
介绍
回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志。
当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除。
而update、delete的时候,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会立即被删除。
版本链
有一张表原始数据为:

DB_TRX_ID : 代表最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID,是自增的。
DB_ROLL_PTR :由于这条数据是才插入的,没有被更新过,所以该字段值为null。然后,有四个并发事务同时在访问这张表。

最终生成记录数据:

最终我们发现,不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录。
readview
ReadView(读视图)是快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。
ReadView中包含了四个核心字段:
| 字段 | 含义 |
|---|---|
| m_ids | 当前活跃的事务ID集合 |
| min_trx_id | 最小活跃事务ID |
| max_trx_id | 预分配事务ID,当前最大事务ID+1(因为事务ID是自增的) |
| creator_trx_id | ReadView创建者的事务ID |
而在readview中就规定了版本链数据的访问规则:trx_id 代表当前undolog版本链对应事务ID。
| 条件 | 是否可以访问 | 说明 |
|---|---|---|
| trx_id == creator_trx_id | 可以访问该版本 | 成立,说明数据是当前这个事务更改的。 |
| trx_id < min_trx_id | 可以访问该版本 | 成立,说明数据已经提交了。 |
| trx_id > max_trx_id | 不可以访问该版本 | 成立,说明该事务是在 |
ReadView生成后才开启。 |
| min_trx_id <= trx_id <= max_trx_id | 如果trx_id不在m_ids中,是可以访问该版本的 | 成立,说明数据已经提交。 |
不同的隔离级别,生成ReadView的时机不同:
- READ COMMITTED :在事务中每一次执行快照读时生成ReadView。
- REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。
MVCC的实现原理就是通过 InnoDB表的隐藏字段、UndoLog 版本链、ReadView来实现的。而MVCC + 锁,则实现了事务的隔离性。而一致性则是由redolog 与 undolog保证。


面试官:请说一下Mysql事务实现原理的更多相关文章
- 跟面试官侃半小时MySQL事务,说完原子性、一致性、持久性的实现
提到MySQL的事务,我相信对MySQL有了解的同学都能聊上几句,无论是面试求职,还是日常开发,MySQL的事务都跟我们息息相关. 而事务的ACID(即原子性Atomicity.一致性Consiste ...
- 跟面试官侃半小时MySQL事务隔离性,从基本概念深入到实现
提到MySQL的事务,我相信对MySQL有了解的同学都能聊上几句,无论是面试求职,还是日常开发,MySQL的事务都跟我们息息相关. 而事务的ACID(即原子性Atomicity.一致性Consiste ...
- 面试官一口气问了MySQL事务、锁和MVCC,我
面试官:你是怎么理解InnoDB引擎中的事务的? 候选者:在我的理解下,事务可以使「一组操作」要么全部成功,要么全部失败 候选者:事务其目的是为了「保证数据最终的一致性」. 候选者:举个例子,我给你发 ...
- 面试官:什么是MySQL 事务与 MVCC 原理?
作者:小林coding 图解计算机基础网站:https://xiaolincoding.com/ 大家好,我是小林. 之前写过一篇 MySQL 的 MVCC 的工作原理,最近有读者在网站上学习的时候, ...
- 面试官问你:MYSQL事务和隔离级别,该如何回答
一.事务 事务是由一组SQL语句组成的逻辑处理单元,是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚.事务具有以下4个属性,通常简称为事务 ...
- 【MySQL】面试官问我:MySQL如何实现无数据插入,有数据更新?我是这样回答的!
写在前面 马上就是金九银十的跳槽黄金期了,很多读者都开始出去面试了.这不,又一名读者出去面试被面试官问了一个MySQL的问题:向MySQL中插入数据,如何实现MySQL中没有当前id标识的数据时插入数 ...
- Mysql 事务及其原理
Mysql 事务及其原理 什么是事务 什么是事务?事务是作为单个逻辑工作单元执行的一系列操作,通俗易懂的说就是一组原子性的 SQL 查询.Mysql 中事务的支持在存储引擎层,MyISAM 存储引擎不 ...
- java面试一日一题:mysql事务是如何实现的
问题:请讲下mysql的事务是如何实现的 分析:该问题主要考察对事务的理解及实现方式: 回答要点: 主要从以下几点去考虑, 1.对事务的概念的理解? 2.事务的实现方式? 讲到mysql的事务,很快可 ...
- 【Java面试】请说一下ReentrantLock的实现原理?
一个工作了3年的粉丝私信我,在面试的时候遇到了这样一个问题. "请说一下ReentrantLock的实现原理",他当时根据自己的理解零零散散的说了一些. 但是似乎没有说到关键点上, ...
- MySQL事务实现原理
MySQL事务隔离级别的实现原理 知识储备 只有InnoDB支持事务,所以这里说的事务隔离级别是指InnoDB下的事务隔离级别 隔离级别 读未提交:一个事务可以读取到另一个事务未提交的修改.这会带来脏 ...
随机推荐
- 在deepin上使用Fleet开发SpringBoot 3.0.0项目
前言 Fleet被称为是由 JetBrains 打造的下一代 IDE,目前出于公测状态,可以免费下载使用. SpringBoot 3.0.0最小支持是JDK 17,这或许是对于JDK8的断舍离迈出的重 ...
- Go 基础之基本数据类型
Go 基础之基本数据类型 目录 Go 基础之基本数据类型 一.整型 1.1 平台无关整型 1.1.1 基本概念 1.1.2 分类 有符号整型(int8~int64) 无符号整型(uint8~uint6 ...
- 基于 ACK Serverless 解锁你家萌宠的 AI 形象
基于 ACK Serverless 解锁你家萌宠的 AI 形象详情 1. 计费说明 必看!!必看!!必看!! 本实验为付费体验,需要消耗账号费用.体验后若不再需要使用,请及时释放资源,避免持 ...
- 【Cucumber】关于BDD自然语言自动化测试的语法总结
1.关键字 - Feature 每一个.feature文件必须以关键字Feature开始,Feature关键字之后可以添加该feature的描述,其作用类似于注释,仅仅为了便于理解沟通交流,描述内容中 ...
- Tinyalsa PCM API 实现深度剖析
高级 Linux 音频架构 (ALSA) 用于为 Linux 操作系统提供音频和 MIDI 功能.它可以高效地支持所有类型的音频接口,从消费者声卡到专业的多通道音频接口.它支持全模块化的音频驱动.它是 ...
- ciscn_2019_c_1 题解
main函数如下: int __cdecl main(int argc, const char **argv, const char **envp) { int v4; // [rsp+Ch] [rb ...
- 【Unity3D】Shader Graph节点
1 前言 Shader Graph 16.0.3 中有 208 个 Node(节点),本文梳理了 Shader Graph 中大部分 Node 的释义,官方介绍详见→Node-Library. ...
- [ABC205E] White and Black Balls 题解
White and Black Balls 题目大意 将 \(n\) 个白球,\(m\) 个黑球排成一列,要求满足 \(\forall i\in[1,n+m],w_i\le b_i+k\),问存在多少 ...
- kubernetes发布周期
前言 页面介绍了版本发布的一些时间点和PR的要求,通过了解k8s的发布周期来规划自己的版本选择. 合并PR的要求 如果你希望将你的代码合并到官方代码仓库中,不同的开发阶段需要有不同的标签和里程碑.也是 ...
- python加解密小工具
1.地址 https://github.com/Doneone/RSA_GUI 2.用法 python3 rsa_gui.py 创建密钥对 3.思考 为什么要写rsa小工具呐,因为单纯想实现一个简单的 ...