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

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.hqwc.cn/news/452038.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k8s学习-Kubernetes的包管理器Helm

1.1 为何需要Helm Kubernetes能够很好地组织和编排容器,但它缺少⼀个更高层次的应用打包工具,而Helm就是来干这件事的。 先来看个例子。 比如对于⼀个MySQL服务,Kubernetes需要部署下面这些对象: (1)Serv…

【消息队列】kafka整理

kafka整理 整理kafka基本知识供回顾。

vulhub中spring的CVE-2022-22965漏洞复现

在JDK 9上运行的Spring MVC或Spring WebFlux应用程序可能存在通过数据绑定执行远程代码(RCE)的漏洞。 现在已知的利用方法要求应用程序以WAR部署的形式在Tomcat上运行,然而,该漏洞的性质更为普遍,可能有其他方法可以利…

C++友元函数/友元类

目录 1.友元函数/友元类定义2.友元函数、类成员函数、非友元函数的区别3.友元函数和友元类的比较4.友元函数/友元类的优缺点5.参考内容 1.友元函数/友元类定义 (1)在类中用friend关键字去声明函数/类,则这个函数/类就会变成友元函数/友元类; (2)友元函数…

Zookeeper 集群安装

载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一,它通常是指,将请求/数据【均匀】分摊到多个操作单元上执行,负载均衡的关键在于【均匀】。常见互联网分布式架构如上,分为客户端层、反向代理nginx层、站点层、服务层、数据层。 现在使用最多的基于软件的负…

鉴权失败原因

在技术领域,鉴权失败是指一个系统或应用程序中的身份验证或权限验证过程失败。当用户试图访问受限资源或执行受限操作时,系统会进行鉴权过程来确认用户是否具有足够的权限。如果鉴权过程失败,则表示用户无法获得所需的访问权限。 鉴权失败可…

【学网攻】 第(20)节 -- 网络端口地址转换NAPT配置

系列文章目录 目录 系列文章目录 文章目录 前言 一、NAPT是什么? 二、实验 1.引入 实验目的 技术原理 实验步骤 实验设备 实验拓扑图 实验配置 实验验证 文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻】 第(2)节 -- 交换机认识及使用【学网攻】 第…

AtCoder Beginner Contest 339 A-E 题解

A - TLD AtCoder: A - TLD 洛谷: [ABC339A] TLD 思路 从后往前枚举&#xff0c;找到最后一个 所在的位置&#xff0c;输出它后面的所有字符&#xff08;不包含 &#xff09;。 代码 #include<iostream> using namespace std; int main() {string s;cin >> …

Facebook群控:利用IP代理提高聊单效率

在当今社交媒体竞争激烈的环境中&#xff0c;Facebook已经成为广告营销和推广的重要平台&#xff0c;为了更好地利用Facebook进行推广活动&#xff0c;群控技术应运而生。 本文将深入探讨Facebook群控的定义、作用以及如何利用IP代理来提升群控效率&#xff0c;为你提供全面的…

Java实现批量视频抽帧2.0

继上个版本 对其进行略微升级 &#x1f913; 上个版本仅对一个视频进行抽帧处理 此版本可对一个文件夹内的全部视频进行抽帧并对应的文件夹进行帧图片的保存 1️⃣配置pom.xml &#xff08;保持上次不变&#xff09; <dependencies><dependency><grou…

100183. 最大好子数组和

题目&#xff1a; 给你一个长度为 n 的数组 nums 和一个 正 整数 k 。 如果 nums 的一个子数组中&#xff0c;第一个元素和最后一个元素 差的绝对值恰好 为 k &#xff0c;我们称这个子数组为 好 的。换句话说&#xff0c;如果子数组 nums[i..j] 满足 |nums[i] - nums[j]| k…

oc渲染器初始参数怎么设置?oc渲染器初始参数怎么弄

OC渲染器以其用户友好的界面、卓越的渲染品质而受到众多初学者的欢迎&#xff0c;而且它使得创建逼真的视觉效果变得轻而易举。对于产品展示、建筑设计以及室内布局渲染来说&#xff0c;OC渲染器都能表现出优异的性能。下面&#xff0c;我们将介绍新手如何进行OC渲染器的基本初…