当前位置: 首页 > news >正文

【MySQL】MySQL的事务原理和实现?

文章目录

  • MySQL事务的底层实现原理
  • 一、事务的目的
    • 可靠性和并发处理
  • 二、实现事务功能的三个技术
    • 2.1 redo log 与 undo log介绍
      • 2.1.1 redo log
      • 2.1.2undo log
    • 2.2 mysql锁技术
      • 2.2.1 mysql锁技术
    • 2.3 MVCC基础
  • 三、事务的实现
    • 3.1 原子性的实现
      • 3.1.1 undo log 的生成
      • 3.1.2 根据undo log 进行回滚
    • 3.2 持久性的实现
    • 3.3 隔离性实现
      • 3.3.1 READ UNCOMMITTED
      • 3.3.2 READ COMMITTED
      • 3.3.3 REPEATABLE READ(Mysql默认隔离级别)
      • 3.3.4 SERIALIZABLE
    • 3.4 一致性的实现
  • 总结

MySQL事务的底层实现原理

特点ACID:

  • 原子性(Atomicity)

  • 一致性(Consistency)

  • 隔离型(Isolation)

  • 持久性(Durability)

一、事务的目的

可靠性和并发处理

  • 可靠性:数据库要保证当insert或update操作时抛异常或者数据库crash的时候需要保障数据的操作前后的一致,想要做到这个,我需要知道我修改之前和修改之后的状态,所以就有了undo log和redo log。

  • 并发处理:也就是说当多个并发请求过来,并且其中有一个请求是对数据修改操作的时候会有影响,为了避免读到脏数据,所以需要对事务之间的读写进行隔离,至于隔离到啥程度得看业务系统的场景了,实现这个就得用MySQL 的隔离级别。

二、实现事务功能的三个技术

  • 日志文件(redo log 和 undo log)

  • 锁技术

  • MVCC

2.1 redo log 与 undo log介绍

2.1.1 redo log

  • 什么是redo log ?

    redo log叫做重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log),前者是在内存中,后者在磁盘中。

    当事务提交之后会把所有修改信息都会存到该日志中。假设有个表叫做tb1(id,username) 现在要插入数据(3,ceshi)

在这里插入图片描述

start transaction;                                     
select balance from bank where name="zhangsan";         // 生成 重做日志 balance=600                                 update bank set balance = balance - 400;                // 生成 重做日志 amount=400                               update finance set amount = amount + 400;          commit
  • redo log 有什么作用?

    mysql 为了提升性能不会把每次的修改都实时同步到磁盘,而是会先存到Boffer Pool(缓冲池)里头,把这个当作缓存来用。然后使用后台线程去做缓冲池和磁盘之间的同步。

    那么问题来了,如果还没来的同步的时候宕机或断电了怎么办?这样会导致丢部分已提交事务的修改信息!

    所以引入了redo log来记录已成功提交事务的修改信息,并且会把redo log持久化到磁盘,系统重启之后在读取redo log恢复最新数据。

  • 总结
    redo log是用来恢复数据的 用于保障已提交事务的持久化特性。

2.1.2undo log

  • 什么是 undo log ?

    undo log 叫做回滚日志,用于记录数据被修改前的信息。他正好跟前面所说的重做日志所记录的相反,重做日志记录数据被修改后的信息。undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。

    每次写入数据或者修改数据之前都会把修改前的信息记录到 undo log。

  • undo log 有什么作用?

    undo log 记录事务修改之前版本的数据信息,因此假如由于系统错误或者rollback操作而回滚的话可以根据undo log的信息来进行回滚到没被修改前的状态。

  • 总结
    undo log是用来回滚数据的用于保障 未提交事务的原子性

2.2 mysql锁技术

2.2.1 mysql锁技术

当有多个请求来读取表中的数据时可以不采取任何操作,但是多个请求里有读请求,又有修改请求时必须有一种措施来进行并发控制。不然很有可能会造成不一致。

  • 读写锁

解决上述问题很简单,只需用两种锁的组合来对读写请求进行控制即可,这两种锁被称为:

  • 共享锁(shared lock),又叫做"读锁"

读锁是可以共享的,或者说多个读请求可以共享一把锁读数据,不会造成阻塞。

  • 排他锁(exclusive lock),又叫做"写锁"

写锁会排斥其他所有获取锁的请求,一直阻塞,直到写入完成释放锁。

在这里插入图片描述

  • 总结
    通过读写锁,可以做到读读可以并行,但是不能做到写读,写写并行,事务的隔离性就是根据读写锁来实现的。

2.3 MVCC基础

MVCC (MultiVersion Concurrency Control) 叫做多版本并发控制。

InnoDB的 MVCC ,是通过在每行记录的后面保存两个隐藏的列来实现的。

这两个列,一个保存了行的创建时间,一个保存了行的过期时间,当然存储的并不是实际的时间值,而是系统版本号

他的主要实现思想是通过数据多版本来做到读写分离。从而实现不加锁读进而做到读写并行.。

MVCC在mysql中的实现依赖的是undo log与read view

undo log :undo log 中记录某行数据的多个版本的数据。

read view :用来判断当前版本数据的可见性

在这里插入图片描述

三、事务的实现

  • 事务的原子性是通过undolog来实现的

  • 事务的持久性性是通过redolog来实现的

  • 事务的隔离性是通过(读写锁+MVCC)来实现的

  • 事务的终极大 boss 一致性是通过原子性,持久性,隔离性来实现的!!!

原子性,持久性,隔离性的目的也是为了保障数据的一致性!

总之,ACID只是个概念,事务最终目的是要保障数据的可靠性,一致性。

3.1 原子性的实现

  • 什么是原子性:

一个事务必须被视为不可分割的最小工作单位,一个事务中的所有操作要么全部成功提交,要么全部失败回滚,对于一个事务来说不可能只执行其中的部分操作,这就是事务的原子性。

以上概念相信大家伙儿都了解,那么数据库是怎么实现的呢?就是通过回滚操作。所谓回滚操作就是当发生错误异常或者显式的执行rollback语句时需要把数据还原到原先的模样,所以这时候就需要用到undo log来进行回滚,接下来看一下undo log在实现事务原子性时怎么发挥作用的

3.1.1 undo log 的生成

假设有两个表 bank和finance,当进行插入,删除以及更新操作时生成的undo log。

在这里插入图片描述

从上图可以了解到数据的变更都伴随着回滚日志的产生:

  • 产生了被修改前数据(zhangsan,1000) 的回滚日志

  • 产生了被修改前数据(zhangsan,0) 的回滚日志

根据上面流程可以得出如下结论:

  1. 每条数据变更(insert/update/delete)操作都伴随一条undo log的生成,并且回滚日志必须先于数据持久化到磁盘上

  2. 所谓的回滚就是根据回滚日志做逆向操作,比如delete的逆向操作为insert,insert的逆向操作为delete,update的逆向为update等。

3.1.2 根据undo log 进行回滚

为了做到同时成功或者失败,当系统发生错误或者执行rollback操作时需要根据undo log 进行回滚

img

回滚操作就是要还原到原来的状态,undo log记录了数据被修改前的信息以及新增和被删除的数据信息,根据undo log生成回滚语句,比如:

(1) 如果在回滚日志里有新增数据记录,则生成删除该条的语句

(2) 如果在回滚日志里有删除数据记录,则生成生成该条的语句

(3) 如果在回滚日志里有修改数据记录,则生成修改到原先数据的语句

3.2 持久性的实现

事务一旦提交,其所做的修改会永久保存到数据库中,此时即使系统崩溃修改的数据也不会丢失。

先了解一下MySQL的数据存储机制,MySQL的表数据是存放在磁盘上的,因此想要存取的时候都要经历磁盘IO,然而即使是使用SSD磁盘IO也是非常消耗性能的。为此,为了提升性能InnoDB提供了缓冲池(Buffer Pool),Buffer Pool中包含了磁盘数据页的映射,可以当做缓存来使用:

读数据:会首先从缓冲池中读取,如果缓冲池中没有,则从磁盘读取再放入缓冲池;

写数据:会首先写入缓冲池,缓冲池中的数据会定期同步到磁盘中;

上面这种缓冲池的措施虽然在性能方面带来了质的飞跃,但是它也带来了新的问题,当MySQL系统宕机,断电的时候可能会丢数据!!!

因为我们的数据已经提交了,但此时是在缓冲池里头,还没来得及在磁盘持久化,所以我们急需一种机制需要存一下已提交事务的数据,为恢复数据使用。

于是 redo log就派上用场了。下面看下redo log是什么时候产生的

在这里插入图片描述

既然redo log也需要存储,也涉及磁盘IO为啥还用它?

(1)redo log 的存储是顺序存储,而缓存同步是随机操作。

(2)缓存同步是以数据页为单位的,每次传输的数据大小大于redo log。

3.3 隔离性实现

隔离性是事务ACID特性里最复杂的一个。在SQL标准里定义了四种隔离级别,每一种级别都规定一个事务中的修改,哪些是事务之间可见的,哪些是不可见的。

级别越低的隔离级别可以执行越高的并发,但同时实现复杂度以及开销也越大。

MySQL隔离级别有以下四种(级别由低到高):

  1. READUNCOMMITED(未提交读)

  2. READCOMMITED(提交读)

  3. REPEATABLEREAD(可重复读)

  4. SERIALIZABLE (可重复读)

只要彻底理解了隔离级别以及他的实现原理就相当于理解了ACID里的隔离型。前面说过原子性,隔离性,持久性的目的都是为了要做到一致性,但隔离型跟其他两个有所区别,原子性和持久性是为了要实现数据的可性保障靠,比如要做到宕机后的恢复,以及错误后的回滚。

  • 那么隔离性是要做到什么呢?

    隔离性是要管理多个并发读写请求的访问顺序。 这种顺序包括串行或者是并行

    说明一点,写请求不仅仅是指insert操作,又包括update操作。

在这里插入图片描述

总之,从隔离性的实现可以看出这是一场数据的可靠性与性能之间的权衡:

可靠性性高的,并发性能低(比如Serializable)。可靠性低的,并发性能高(比如 Read Uncommited)

3.3.1 READ UNCOMMITTED

在READ UNCOMMITTED隔离级别下,事务中的修改即使还没提交,对其他事务是可见的。事务可以读取未提交的数据,造成脏读。

因为读不会加任何锁,所以写操作在读的过程中修改数据,所以会造成脏读。好处是可以提升并发处理性能,能做到读写并行。

换句话说,读的操作不能排斥写请求。

在这里插入图片描述

优点:读写并行,性能高

缺点:造成脏读

3.3.2 READ COMMITTED

一个事务的修改在他提交之前的所有修改,对其他事务都是不可见的。其他事务能读到已提交的修改变化。在很多场景下这种逻辑是可以接受的。

InnoDB在 READ COMMITTED,使用排它锁,读取数据不加锁而是使用了MVCC机制。或者换句话说他采用了读写分离机制。

但是该级别会产生不可重读以及幻读问题。

  • 什么是不可重读?

在一个事务内多次读取的结果不一样。

  • 为什么会产生不可重复读?

这跟 READ COMMITTED 级别下的MVCC机制有关系,在该隔离级别下每次 select的时候新生成一个版本号,所以每次select的时候读的不是一个副本而是不同的副本。

在每次select之间有其他事务更新了我们读取的数据并提交了,那就出现了不可重复读

3.3.3 REPEATABLE READ(Mysql默认隔离级别)

在一个事务内的多次读取的结果是一样的。这种级别下可以避免,脏读,不可重复读等查询问题。mysql 有两种机制可以达到这种隔离级别的效果,分别是采用读写锁以及MVCC。

采用读写锁实现:

在这里插入图片描述

为什么能可重复读?只要没释放读锁,在次读的时候还是可以读到第一次读的数据。

优点:实现起来简单

缺点:无法做到读写并行

采用MVCC实现:

为什么能可重复读?因为多次读取只生成一个版本,读到的自然是相同数据。

优点:读写并行

缺点:实现的复杂度高

但是在该隔离级别下仍会存在幻读的问题,关于幻读的解决我打算另开一篇来介绍。

3.3.4 SERIALIZABLE

该隔离级别理解起来最简单,实现也最简单。在隔离级别下除了不会造成数据不一致问题,没其他优点。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.4 一致性的实现

数据库总是从一个一致性的状态转移到另一个一致性的状态。

下面举个例子,zhangsan 从银行卡转400到理财账户:


start transaction;                                     select balance from bank where name="zhangsan";         // 生成 重做日志 balance=600                             update bank set balance = balance - 400;                // 生成 重做日志 amount=400                              update finance set amount = amount + 400;           commit;
  1. 假如执行完 update bank set balance = balance - 400;之发生异常了,银行卡的钱也不能平白无故的减少,而是回滚到最初状态。

  2. 又或者事务提交之后,缓冲池还没同步到磁盘的时候宕机了,这也是不能接受的,应该在重启的时候恢复并持久化。

  3. 假如有并发事务请求的时候也应该做好事务之间的可见性问题,避免造成脏读,不可重复读,幻读等。在涉及并发的情况下往往在性能和一致性之间做平衡,做一定的取舍,所以隔离性也是对一致性的一种破坏。

总结

实现事务采取了哪些技术以及思想?

  • 原子性:使用 undo log ,从而达到回滚

  • 持久性:使用 redo log,从而达到故障后恢复

  • 隔离性:使用锁以及MVCC,运用的优化思想有读写分离,读读并行,读写并行

  • 一致性:通过回滚,以及恢复,和在并发环境下的隔离做到一致性。

相关文章:

【MySQL】MySQL的事务原理和实现?

文章目录 MySQL事务的底层实现原理一、事务的目的可靠性和并发处理 二、实现事务功能的三个技术2.1 redo log 与 undo log介绍2.1.1 redo log2.1.2undo log 2.2 mysql锁技术2.2.1 mysql锁技术 2.3 MVCC基础 三、事务的实现3.1 原子性的实现3.1.1 undo log 的生成3.1.2 根据undo…...

S7-300Smart1200的ISO on TCP通信

1、西门子PLC的通信资源 1.1 S7-1200 的PROFINET 通信口 S7-1200 CPU 本体上集成了一个 PROFINET 通信口,支持以太网和基于 TCP/IP 的通信标准。使用这个通信口可以实现 S7-1200 CPU 与编程设备的通信,与HMI触摸屏的通信,以及与其它 CPU 之间的通信。这个PROFINET 物理接口…...

Spark写入Hive报错Mkdir failed on :com.alibaba.jfs.JindoRequestPath

1. 报错内容 23/05/31 14:32:13 INFO [Driver] FsStats: cmdmkdirs, srcoss://sync-to-bi.[马赛克].aliyuncs.com/tmp/hive, dstnull, size0, parameterFsPermission:rwx-wx-wx, time-in-ms32, version3.5.0 23/05/31 14:32:13 ERROR [Driver] ApplicationMaster: User class …...

分布式id解决方法--雪花算法

uuid,jdk自带,但是数据库性能差,32位呀。 mysql数据库主键越短越好,Btree产生节点分裂,大大降低数据库性能,所以uuid不建议。 redis的自增,但是要配置维护redis集群,就为了一个id&a…...

5年经验之谈:月薪3000到30000,测试工程师的变“行”记

自我介绍下,我是一名转IT测试人,我的专业是化学,去化工厂实习才发现这专业的坑人之处,化学试剂害人不浅,有毒,易燃易爆,实验室经常用丙酮,甲醇,四氯化碳,接触…...

PMP考试都是什么题?

PMP新版大纲加入了ACP敏捷管理的内容,说是敏捷混合题型占到了 50%,但是这次318的考试,敏捷题占了大半,都说敏捷和情景快要占到80%-90%。 所以有友友说开了四个小时盲盒,题目读不懂,或者觉得4个选项都不对或…...

macbook2023系统清理软件cleanmymac中文版

cleanmymac x 中文版基本都是大家首选Mac清理软件了。它集各种功能于一身,几乎满足用户所有的清理需求。它可以清理,优化,保养和监测您的电脑,确保您的Mac运行畅通无阻!支持一键快速清理Mac,快速检查并安全…...

基于Python+AIML+Tornado的智能聊天机器人(NLP+深度学习)含全部工程源码+语料库 适合个人二次开发

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境Tornado 环境 模块实现1. 前端2. 后端3. 语料库4. 系统测试 其它资料下载 前言 本项目旨在利用AIML技术构建一个聊天机器人,实现用户通过聊天界面与机器人交互的功能。通过提供的工程源代码&#xf…...

算法Day15 | 层序遍历,102,107,199,637,429,515,116,117,104,111,226,101

Day15 层序遍历102.二叉树的层序遍历107.二叉树的层次遍历 II199.二叉树的右视图637.二叉树的层平均值429.N叉树的层序遍历515.在每个树行中找最大值116.填充每个节点的下一个右侧节点指针117.填充每个节点的下一个右侧节点指针II104.二叉树的最大深度111.二叉树的最小深度 226…...

Prometheus+Grafana学习(十一)安装使用pushgateway

Pushgateway允许短暂和批量作业将其指标暴露给 Prometheus。由于这些工作的生命周期可能不足够长,不能够存在足够的时间以让 Prometheus 抓取它们的指标。Pushgateway 允许它们可以将其指标推送到 Pushgateway,然后 Pushgateway 再将这些指标暴露给 Prom…...

深入理解C/C++预处理器指令#pragma once以及与ifndef的比较

#pragma once用法总结 为了防止重复引用造成二义性 在C/C中,在使用预编译指令#include的时候,为了防止重复引用造成二义性,通常有两种方式 第一种是#ifndef指令防止代码块重复引用,比如说 #ifndef _CODE_BLOCK #define _CODE_BLO…...

git 环境配置 + gitee拉取代码

好嘛 配环境的时候 老是忘记这个命令行 干脆自己写一个记录一下 也不用搜了 1.先从git官网下载git 安装 2.然后从gitee拉取代码的时候提示 这是因为换了新电脑没有加入新的公钥啦 哎 所以老是记不住命令行 first : git config --global user.name “Your Name” …...

港联证券|港股拥抱特专科技企业 内资券商“修炼内功”蓄势而为

港股市场新一轮改革举措渐次落地。特别是港交所推出特专科技公司上市机制,吸引符合资格的科技企业申请赴港上市,成为这一轮港股市场改革的“重头戏”。 作为香港资本市场的重要参与者,内资券商立足香港、背靠内地、辐射全球,走出一…...

多项创新技术加持,实现零COGS的Microsoft Editor语法检查器

编者按:Microsoft Editor 是一款人工智能写作辅助工具,其中的语法检查器(grammar checker)功能不仅可以帮助不同水平、领域的用户在写作过程中检查语法错误,还可以对错误进行解释并给出正确的修改建议。神经语法检查器…...

Python编程环境搭建:Windows中如何安装Python

在 Windows 上安装 Python 和安装普通软件一样简单,下载安装包以后猛击“下一步”即可。 Python 安装包下载地址:https://www.python.org/downloads/ 打开该链接,可以看到有两个版本的 Python,分别是 Python 3.x 和 Python 2.x&…...

Sui Builder House首尔站倒计时!

Sui主网上线后的第一场Builder House活动即将在韩国首尔举行,同期将举办首场线下面对面的黑客松。活动历时两天,将为与会者提供独特的学习、交流和娱乐的机会。活动详情请查看:Sui Builder House首尔站|主网上线后首次亮相。 Sui…...

Java设计模式-状态模式

简介 在软件开发领域,设计模式是一组经过验证的、被广泛接受的解决问题的方案。其中之一是状态模式,它提供了一种优雅的方式来管理对象的不同状态。 状态模式是一种行为型设计模式,它允许对象在内部状态发生改变时改变其行为。状态模式将对…...

智慧社区用什么技术开发

智慧社区是指利用信息技术和先进的管理理念,将社区内的各种公共服务进行整合和优化,提高社区居民的生活品质和社区管理的效率。为了实现智慧社区的建设,需要采用多种技术,包括但不限于以下几种: 1.物联网技术&#xf…...

多线程 线程池饱和策略

RejectedExecutionHandler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。 这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。 在JDK 1…...

进程间通信之信号

进程间通信之信号 1. 信号2. 信号由谁产生?3. 有哪些信号4. 信号的安装5. 信号的发送1) 使用kill函数2)使用alarm函数3) 使用raise6.发送多个信号7. 信号集1. 信号 什么是信号? 信号是给程序提供一种可以处理异步事件的方法,它利用软件中断来实现。不能自定义信号,所有信号…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

AI,如何重构理解、匹配与决策?

AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

【生成模型】视频生成论文调研

工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...

day36-多路IO复用

一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...

深入浅出Diffusion模型:从原理到实践的全方位教程

I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...

面试高频问题

文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...