MySQL知识点总结(三)——事务

news2024/11/28 22:47:49

MySQL知识点总结(三)——事务

  • 事务
    • 事务的四大特性ACID
      • 原子性
      • 一致性
      • 隔离性
      • 持久性
    • 脏读、幻读、不可重复读
      • 脏读
      • 不可重复读
      • 幻读
    • 隔离级别
      • 读未提交
      • 读已提交
      • 可重复读
      • 串行化
    • 事务的原理
      • InnoDB如何实现事务的ACID
      • 事务的两阶段提交
        • redo log与binlog的区别
        • 事务两阶段提交流程
        • 为什么要两阶段提交,一阶段不行吗?
      • redo log、undo log、binlog
        • redo log
        • binlog
        • undo log

事务

事务是保证一批SQL同时成功或同时失败的一种机制,是保证一致性的一种手段。

事务的四大特性ACID

  • A:原子性
  • C:一致性
  • I:隔离性
  • D:持久性

在这里插入图片描述

原子性

事务的原子性是指事务是一个原子性的操作,必须保证同一个事务里面的这一批SQL同时成功或同时失败,不可以某些成功某些失败。

一致性

这个要表达清楚还真不容易,往往需要举例。事务的一致性,是指事务在提交之前,和提交之后,事务涉及到的所有修改的表记录,它们的状态的变化是保持一致。比如银行转账。。。。(还是不说了,这例子都被举烂掉了)

在这里插入图片描述

隔离性

事务的隔离性是指两个事务之间互不影响,互不干扰。

持久性

事务的持久性是指事务一旦提交,涉及的修改是持久生效的。

脏读、幻读、不可重复读

这是事务可能会发生的三大问题。

在这里插入图片描述

脏读

当前事务读取到了另一个事务还没有提交的修改,如果另一个事务把这个修改回滚了,那么就相当于是读到了脏数据。

不可重复读

当前事务对同一行数据的读取,前后两次读到了不同的结果。出现这种情况,一般是隔离级别设的不够高,其他事务对该行数据做了修改后提交了,当前事务再次读取,就是修改后的值,因此出现了前后两次读到的值不一致。

幻读

当前事务前后两次读取,读到的记录数不一致,比如前面读到了9条,后面再次读取读到了10条,多出了一条,这就好像出现了幻觉。出现这种情况,一般是其他事务在当前事务第一次读取后,在读取范围内新增了数据,导致当前事务第二次读取时读到了其他事务新增的数据。

隔离级别

  • 读未提交
  • 读已提交
  • 可重复读
  • 串行化

读未提交

当前事务可以读到其他事务还没有提交的修改。这种隔离级别是最低的,无法防止脏读、不可重复读和幻读。

读已提交

当前事务只能读取到其他事务已经提交的修改,其他事务没有提交的修改则不能被当前事务读取到。这是大多数数据库默认的隔离级别,但是MySQL并没有把它作为默认的隔离级别。这种隔离级别下可以防止脏读,但是无法防止不可重复读和幻读。

可重复读

比读已提交更严格的隔离级别,是MySQL默认的隔离级别。在这种隔离级别下,可以保证一个事务内,对同一条记录的读取,总是能读到相同的结果。可以防止脏读和不可重复读,但是还是有可能出现幻读。

串行化

最严格的隔离级别,一般很少会使用,隔离性最高,但是性能最低。在这种隔离级别下,可以认为事务是一个个串行执行的(读读可以并行),事务的读取会加读锁,修改会加写锁。这种隔离级别可以防止脏读、幻读、不可重复读。

在这里插入图片描述

事务的原理

InnoDB如何实现事务的ACID

事务的原子性,通过undo log实现,undo log可以理解为数据库表行记录的历史版本,每次事务对库表的行记录进行修改时,都会先记录它的历史版本到undo log中,如果该事务回滚了,那么就从undo log中读取行记录的历史版本,把它还原回去。

事务的隔离性通过锁和MVCC(多版本并发控制)保证。如果一个事务对一行或多行加了锁,其他事务自然是无法对它们进行修改,也就达到了隔离效果,只是加锁这种隔离手段代价太高了,会阻塞其他事务的执行。于是就有了MVCC,MVCC是多版本并发控制,简单理解就是一个行记录可以同时存在多个版本,那么不同事务间读写同一个行记录的不同的版本,自然可以互不影响。

事务的持久性是通过redo log实现的,redo log是一种WAL(预写日志)机制,一个事务提交了对库表行记录的修改,InnoDB并不会马上持久化到磁盘的索引页中,因为磁盘中的索引页读写是随机读写,性能是极低的,InnoDB会通过redo log记录“某索引页,某个位置,要修改成某某值”之类的日志,把它持久化到磁盘,假设MySQL宕机了,重启之后也可以利用redo log恢复,这样就不会发生更新丢失,这就是redo log的作用,而redo log在磁盘中是顺序写的,性能是极高的,这样就满足了持久性的同时又保证了性能。

而一致性,是最终目的,满足了原子性、隔离性和持久性,才能满足一致性。

在这里插入图片描述

事务的两阶段提交

redo log与binlog的区别

除了redo log、undo log以外,MySQL还有一个binlog。binlog与redo log的功能看似很相似,实际上并不一样。

redo log是InnoDB存储引擎独有的,binlog是属于MySQL服务端的,是所有存储引擎共享的。

redo log记录的是索引页的修改,是用于崩溃恢复的,比如有一个事务提交了,修改记录到redo log中,但是没有持久化到磁盘索引页,此时MySQL宕机了,当我们重启MySQL后,InnoDB就会自动使用redo log去恢复索引页,把更新持久化到索引页中。而binlog日志记录的是事务提交的SQL本身,是用于备份和主从同步到,当然遇到删库跑路的场景,也可以用它来恢复到某个时间点。

因此当一个事务提交时,需要保证redo log和binlog的一致性。

事务两阶段提交流程

当一个事务要提交时,首先InnoDB会记录redo log日志,并持久化到磁盘,并修改日志的状态位prepare状态,然后响应MySQL服务端。当服务端收到响应时,会记录binlog并持久化。然后服务端再调InnoDB存储引擎,执行真正的事务提交,此时InnoDB把redo log的状态改为commit状态。

在这里插入图片描述

为什么要两阶段提交,一阶段不行吗?

我们看一下当MySQL宕机重启后,两阶段提交的各种可能情况。

当MySQL宕机重启时,检查发现事务提交后记录了redo log处于prepare状态,而binlog并没有记录,那么会把记录的redo log日志回滚掉,这相当于是事务提交失败了,但是redo log和binlog是保持一致的。

如果事务提交时记录了redo log处于prepare状态,并且MySQL服务端也记录了binlog,此时才宕机的,那么MySQL重启后会把redo log提交,这样事务就算是提交成功了,redo log和binlog也是一致的。

如果是redo log和binlog都没有记录,或者redo log记录了并处于commit状态并且MySQL服务端也记录了binlog,这两种情况本身就是一致的。

在这里插入图片描述

嗯~~~,怎么看都是没有问题,横竖都是一致的。

那假如改成了一阶段提交呢?

比如先提交redo log,再记录binlog,此时就有可能出现这种情况:提交完redo log后MySQL宕机了,没来得及记录binlog,此时MySQL重启后,发现redo log是有的,于是当前库表的修改是生效的,但是如果我们配了主从同步,由于binlog上是没有修改记录的,因此同步到从库时,从库就少了一次修改。

在这里插入图片描述

那改成先记录binlog,再提交redo log呢?那又有可能出现另一个问题:MySQL服务端记录了binlog,此时MySQL宕机了,InnoDB没来得及提交redo log。当MySQL重启时,发现没有redo log,那么当前数据库的库表是不存在此次事务的修改的,但是binlog却记录事务的修改,同步到从库时,从库就比主库多了一次更新,于是又出现了主从不一致。

在这里插入图片描述

redo log、undo log、binlog

redo log

redo log是“重做日志”,它的作用就是可以使得InnoDB每次执行SQL的增删改操作,修改了数据行记录之后,无需马上把修改持久化到磁盘,而是记一条redo log日志,redo log是顺序写入的,写入速度非常快,大大提高了写入更新的性能。而数据索引页的修改,InnoDB会异步的以随机写入的方式写入到磁盘,如果没来得及写入就宕机了,InnoDB可以利用redo log去恢复,数据的更新不会丢失。

redo log记录的是索引页的修改,类似于“某个索引页,某某位置,修改为xxx”,是物理日志,物理层面的修改。

redo log是固定大小的,我们可以配置它的固定大小,以及分成几个文件。redo log 有一个 write pos指针,指向当前写入到的位置,当redo log写满之后,就会回到开头,此时会覆盖掉最开始写入的日志。redo log还有一个check point指针,当数据更新被持久化到磁盘数据索引页后,check point会往前推进,write pos到check point之间的区域都是可以覆盖的。当write pos追上check point后,InnoDB只能停止redo log的写入,先把一部分数据更新到磁盘,把check point往前推一段距离,让write pos有空间可以写入。

在这里插入图片描述

binlog

binlog是二进制日志,与redo log不同的是,binlog是属于MySQL服务端日志,是所有存储引擎共享的,而redo log是InnoDB存储引擎专有的日志,只有使用了InnoDB存储引擎,才有redo log日志。

binlog是二进制归档日志,记录的是SQL语句的逻辑,比如“给某某表的某某id的行记录的某某字段的值改为xxx”,因此执行binlog是需要经过解析的,不像redo log那样拿到之后可以直接重放。

binlog是不固定大小的,写满了一个文件,再新开一个。

binlog是不具备崩溃自动恢复的能力的,它不像redo log,binlog的作用主要用于归档,也就是用来做备份,当有人删库跑路时,我们可以拿它来人工手动恢复出一个某时间点的库,不至于删完就GG,同时也可以用于主从同步。

在这里插入图片描述

在这里插入图片描述

undo log

undo log是回滚日志,顾名思义,它是在事务回滚时使用的,所以它的一大作用是事务事务回滚。

undo log记录的是行记录的历史版本,当事务发生回滚时,就从undo log中拿到该行记录的历史版本,恢复回去。

在这里插入图片描述

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

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

相关文章

基于SpringBoot+Vue的在线教育平台设计与实现

目录 项目介绍 技术栈 项目介绍 项目截图 搭建 代码截取 代码获取 项目介绍 近年由于疫情影响,线下教育行业受到较大冲击,因此线上教育培训有较好的发展势头,其中建筑行业考证培训是一个前景良好的发展方向,该行业不仅需要…

权威认可|亚数强势入围FreeBuf《CCSIP 2023中国网络安全产业全景图》10大细分领域

近日,国内安全行业门户FreeBuf旗下FreeBuf咨询正式发布《CCSIP(China Cyber Security Industry Panorama)2023中国网络安全行业全景册(第六版)》。 凭借卓越的技术产品能力、市场影响力及领先的综合实力,亚…

C++泛编程(3)

类模板基础 1.类模板的基本概念2.类模板的分文件编写3.类模板的嵌套 (未完待续...) 在往节内容中,我们详细介绍了函数模板,这节开始我们就来聊一聊类模板。C中,类的细节远比函数多,所以这个专题也会更复杂。…

【Crypto | CTF】BUUCTF 萌萌哒的八戒

天命:这年头连猪都有密码,真是奇葩,怪不得我一点头绪都没有 拿到软件,发现是.zip的压缩包,打不开,改成7z后缀名,打开了 发现是一张图片 也只有下面这行东西是感觉是密码了,又不可能…

[leetcode] 22. 括号生成

文章目录 题目描述解题方法方法一:dfs遍历java代码 方法二:按照卡特兰数的思路递归求出有效括号组合java代码 相似题目 题目描述 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 示…

计算机编码:原码、反码、补码的思想、原理和实例(详细版)

​ 目录 收起 一、原码、反码、补码的意义 意义: 三、原码 原码的特点: 原码存在的问题: 四、反码 反码的特点: 存在的问题: 五、补码 六、补码的思想(模&&同余数) 模 && 同余数…

exF2FS: Transaction Support in Log-Structured Filesystem——泛读笔记

FAST 2022 Paper 分布式元数据论文汇总 问题 现代应用程序努力以崩溃一致的方式保护其数据,这通常分布在多个文件抽象之上。在底层文件系统缺乏事务支持的情况下,应用程序使用复杂的协议来确保跨多个文件的事务性更新,产生长序列的写操作和…

小林Coding_操作系统_读书笔记

一、硬件结构 1. CPU是如何执行的 冯诺依曼模型:中央处理器(CPU)、内存、输入设备、输出设备、总线 CPU中:寄存器(程序计数器、通用暂存器、指令暂存器),控制单元(控制CPU工作&am…

自研人工智能小工具-小蜜蜂(国外ChatGpt的平替)

国内有非常多好用的人工智能工具,但均无法完全替代国外ChatGpt。 ChatGPT相较于其他国内工具的优势在于以下几点: 创新的语言生成能力:ChatGPT是由OpenAI开发的先进的自然语言生成模型,它采用了大规模的预训练和精细调整方法。因此…

蓝桥杯刷题day06——平均

1、题目描述 有一个长度为n 的数组(n 是 10 的倍数),每个数ai都是区间 [0,9] 中的整数。 小明发现数组里每种数出现的次数不太平均,而更改第i 个数的代价为bi, 他想更改若干个数的值使得这10 种数出现的次数相等&…

创建TextMeshPro字体文件

相比于Unity的Text组件,TextMesh Pro提供了更强大的文本格式和布局控制,更高级的文本渲染技术,更灵活的文本样式和纹理支持,更好的性能以及更易于使用的优点。但unity自带TextMeshPro字体不支持中文。这里使用普通字体文件生成Tex…

前端登陆加密解决方案

项目背景 环食药烟草的数据下载模块中,需要判断用户在进行数据下载时是进行了登录操作,如果没有登录要跳转登陆页面,输入账号和密码进行登录。 使用场景 项目中需要前端书写登录页面,用户输入账号密码,前端获取到用…

Allegro中设置让Route Keepout(禁止布线区)允许布线或打过孔的方法

Allegro中设置让Route Keepout(禁止布线区)允许布线或打过孔的方法 Chapter1 Allegro中设置让Route Keepout(禁止布线区)允许布线或打过孔的方法一、前言二、设置方法 Chapter2 Cadence Allegro PCB设计88问解析(二十三) 之 Alleg…

QT中QComboBox添加点击事件,实现下拉框自动刷新

因为项目需要,在QT中的ui界面添加QComboBox控件,需求是实现控件的点击事件,查了资料,发现这个控件类的本身是没有点击信号可以使用的。 但是QT是基于C的面向对象,有了这个特点,我们就可以继承原来的类&…

认识Tomcat (一)

认识Tomcat (一) 一、服务器 1.1 服务器简介 ​ 硬件服务器的构成与一般的PC比较相似,但是服务器在稳定性、安全性、性能等方面都要求更高,因为CPU、芯片组、内存、磁盘系统、网络等硬件和普通PC有所不同。 ​ 软件服务器&…

Docker 搭建mysql 集群(二)

PXC方案 很明显 PXC方案在任何一个节点写入的数据都会同步到其他节点,数据双向同步的(在任何节点上都可以同时读写) 创建MySQL PXC集群 1 安装PXC镜像 docker pull percona/percona-xtradb-cluster:5.7.21 2 为PXC镜像改名 docker tag pe…

从零开始手写mmo游戏从框架到爆炸(三)— 服务启动接口与网络事件监听器

上一章我们完成了netty服务启动的相关抽象(https://blog.csdn.net/money9sun/article/details/136025471),这一章我们再新增一个全局的服务启动类,方便后续扩展。 服务启动 新增的两个类如下: 定义一个接口IServer …

react native错误记录

第一次运行到安卓失败 Could not find implementation class com.facebook.react.ReactRootProjectPlugin for plugin com.facebook.react.rootproject specified in jar:file:/D:/Android_Studio_Data/.gradle/caches/jars-9/o_3a1fd35320f05989063e7069031b710f/react-nativ…

Linux命令·

debian linux: deb 软件包 deb软件包分为两种,.deb二进制软件包,.dsc源码包 软件包的两种管理工具 1.dpkg 软件包软件的安装包必须存在 不能从镜像点获得安装包 不能检测软件之间的依赖关系 dpkg -i package.deb #安装包 dpkg -r package …

Elasticsearch:使用 Inference API 进行语义搜索

在我之前的文章 “Elastic Search 8.12:让 Lucene 更快,让开发人员更快”,我有提到 Inference API。这些功能的核心部分始终是灵活的第三方模型管理,使客户能够利用当今市场上下载最多的向量数据库及其选择的转换器模型。在今天的…