在日常工作中,数据库是我们必须使用的,其中使用最多的也是大部分中小公司的选择是Mysql,跳槽面试中也是必问的,今天我们就说一下Mysql事务

MySQL中的事务实现原理主要涉及以下几个方面:

  1. ACID特性:MySQL支持事务的原因之一是它遵循ACID(原子性、一致性、隔离性和持久性)特性。这意味着在一个事务中的所有操作要么全部成功地提交,要么全部失败回滚。这确保了数据的一致性和可靠性。
  2. 日志:MySQL使用日志来记录事务的操作和变化。MySQL有两种主要的日志类型:重做日志(Redo Log)和回滚日志(Undo Log)。
  3. 锁机制:MySQL使用锁机制来实现事务的隔离性,保证并发事务的正确执行。MySQL支持多种类型的锁,如共享锁(Shared Lock)和排他锁(Exclusive Lock),以及行级锁和表级锁等。锁机制可以防止多个事务同时修改同一个数据,保证数据的一致性。
  4. MVCC(多版本并发控制):MVCC是MySQL中的一种并发控制机制,用于在并发事务执行时保证数据的隔离性。MVCC通过在每个数据行上维护多个版本来实现。每个事务在读取数据时,会根据自己的事务ID和数据行的版本信息来确定可见的数据版本,从而实现不同事务之间的隔离性。
  5. 事务管理器: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事务实现原理的更多相关文章

  1. 跟面试官侃半小时MySQL事务,说完原子性、一致性、持久性的实现

    提到MySQL的事务,我相信对MySQL有了解的同学都能聊上几句,无论是面试求职,还是日常开发,MySQL的事务都跟我们息息相关. 而事务的ACID(即原子性Atomicity.一致性Consiste ...

  2. 跟面试官侃半小时MySQL事务隔离性,从基本概念深入到实现

    提到MySQL的事务,我相信对MySQL有了解的同学都能聊上几句,无论是面试求职,还是日常开发,MySQL的事务都跟我们息息相关. 而事务的ACID(即原子性Atomicity.一致性Consiste ...

  3. 面试官一口气问了MySQL事务、锁和MVCC,我

    面试官:你是怎么理解InnoDB引擎中的事务的? 候选者:在我的理解下,事务可以使「一组操作」要么全部成功,要么全部失败 候选者:事务其目的是为了「保证数据最终的一致性」. 候选者:举个例子,我给你发 ...

  4. 面试官:什么是MySQL 事务与 MVCC 原理?

    作者:小林coding 图解计算机基础网站:https://xiaolincoding.com/ 大家好,我是小林. 之前写过一篇 MySQL 的 MVCC 的工作原理,最近有读者在网站上学习的时候, ...

  5. 面试官问你:MYSQL事务和隔离级别,该如何回答

    一.事务 事务是由一组SQL语句组成的逻辑处理单元,是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚.事务具有以下4个属性,通常简称为事务 ...

  6. 【MySQL】面试官问我:MySQL如何实现无数据插入,有数据更新?我是这样回答的!

    写在前面 马上就是金九银十的跳槽黄金期了,很多读者都开始出去面试了.这不,又一名读者出去面试被面试官问了一个MySQL的问题:向MySQL中插入数据,如何实现MySQL中没有当前id标识的数据时插入数 ...

  7. Mysql 事务及其原理

    Mysql 事务及其原理 什么是事务 什么是事务?事务是作为单个逻辑工作单元执行的一系列操作,通俗易懂的说就是一组原子性的 SQL 查询.Mysql 中事务的支持在存储引擎层,MyISAM 存储引擎不 ...

  8. java面试一日一题:mysql事务是如何实现的

    问题:请讲下mysql的事务是如何实现的 分析:该问题主要考察对事务的理解及实现方式: 回答要点: 主要从以下几点去考虑, 1.对事务的概念的理解? 2.事务的实现方式? 讲到mysql的事务,很快可 ...

  9. 【Java面试】请说一下ReentrantLock的实现原理?

    一个工作了3年的粉丝私信我,在面试的时候遇到了这样一个问题. "请说一下ReentrantLock的实现原理",他当时根据自己的理解零零散散的说了一些. 但是似乎没有说到关键点上, ...

  10. MySQL事务实现原理

    MySQL事务隔离级别的实现原理 知识储备 只有InnoDB支持事务,所以这里说的事务隔离级别是指InnoDB下的事务隔离级别 隔离级别 读未提交:一个事务可以读取到另一个事务未提交的修改.这会带来脏 ...

随机推荐

  1. oracle 验证流水存在性火箭试优化

    在生产中经常遇到"select * from  tbl_IsExist where date=?"的SQL,经与开发人员沟通得知此SQL是验证流水存在性,若不存在则插入,若存在退出 ...

  2. 深入理解java和dubbo的SPI机制

    1 SPI简介 1.1 SPI(Service Provider Interface) 本质:将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类.这样可以在运行时,动态为接口替 ...

  3. 开发微信小程序技术栈

    开发微信小程序主要需要以下技术栈: 小程序框架参考文档 小程序组件参考文档 小程序 API 参考文档 小程序服务端 API 参考文档 微信开发者工具参考文档 微信云托管参考文档 微信云开发参考文档 1 ...

  4. MUH and Cube Walls 题解

    MUH and Cube Walls 前言 怎么题解区同质化这么严重,16 篇题解全是 差分 + KMP,就没有人写别的做法吗. (好吧其实是我一开始没想到差分才有了这么多奇怪做法) 题目大意 给定两 ...

  5. Macos下用Clion调试chromium源码

    1:下载CLion 2021.1.3(网上有破解版) 2:选择File->Open 导入chromium源码 3:在Src同级目录新建一个CMakeLists.txt 4:点击clion编译按钮 ...

  6. VK Cup 2016 - Round 1 (CF639)

    A. Bear and Displayed Friends Div2 的题,不写. B. Bear and Forgotten Tree 3 这种东西怎么评蓝的? Description 给定 \(n ...

  7. k 分算法是 k 越大越好吗?

    引入 我们有二分算法,就是: 定义 二分查找(英语:binary search),也称折半搜索(英语:half-interval search).对数搜索(英语:logarithmic search) ...

  8. Python拆分列中文和 字符

    需求描述:我们日常实际的工作中经常需要把一列数据按中文和 数字或者字母单独拆分出来 导入所需的库: import pandas as pd 定义函数 extract_characters,该函数接受三 ...

  9. 【闭包应用】JS:防抖、节流

    1.防抖:当进行连续操作时,只执行最后一次的操作. //防抖的概念是 当进行连续操作时,只执行最后一次的操作. function debounce(fn, delayTime) { let timeo ...

  10. java 处理常量字符串过长 & springboot 项目读取 resouces 文件夹下的文件内容

    长字符串起因 项目里面有一长串的加密字符串(最长的万多个字符),需要拼接作为参数发送给第三方. 如果我们使用 枚举 定义的话,idea 编译的时候就会出现编译报错 Error: java:常量字符串过 ...