【Mysql系列】(二)日志系统:一条更新语句是如何执行的

news2025/1/22 12:15:54

有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top

这篇文章是从Github ReadMe拷贝的,内容实践下载是没问题的,能够正常发送短信,而且也不需要服务器,本地也能跑起来

首发博客地址

系列文章地址


上篇文章我们介绍了一个查询语句的执行流程,并介绍了执行过程中涉及的处理模块。一条查询语句的执行过程一般是经过连接器、分析器、优化器、执行器等功能模块,最后到达存储引擎。

那么,一条语句的更新流程是什么样的?

MySQL可以恢复到半个月内任意一秒的状态,是怎么做到的?

我们先复习下查询流程

alt

这里我们需要注意的是,更新语句的流程和查询流程有两个区别,更新流程涉及两个重要的日志模块:

  • redo log(重做日志)
  • binlog(归档日志)

相信大家在这个面试,学习MySQL的过程中都反复听到这两个词

WAL技术

在MySQL中,WAL(Write-Ahead Logging)技术是一种常用的持久化数据的机制,用于确保数据库的事务操作能够持久化到磁盘并保持数据的一致性。WAL技术的核心思想是在事务进行修改之前,「先将修改操作记录到日志中,然后再将修改应用到数据库中」

具体来说,MySQL中的WAL技术主要包括以下几个组件和步骤:

  1. Redo Log(重做日志):Redo Log是一种事务日志,用于记录数据库中发生的修改操作。在事务提交之前,MySQL会将修改操作写入Redo Log,而不是直接写入磁盘。这样可以提高性能,因为磁盘写入是相对较慢的操作。

  2. Write-Ahead Logging(预写式日志):WAL技术要求在事务提交之前,Redo Log必须先写入磁盘,然后再将修改操作应用到数据库中。这样即使在事务提交后发生系统崩溃,MySQL也可以通过Redo Log来恢复数据。

  3. Redo Log Buffer(重做日志缓冲区):Redo Log Buffer是一个内存缓冲区,用于暂存待写入Redo Log的修改操作。当事务提交时,Redo Log Buffer中的内容会被刷新到磁盘的Redo Log文件中。

  4. Checkpoint(检查点):Checkpoint是一个标记点,表示在这个点之前的所有事务已经持久化到磁盘。MySQL会定期将Checkpoint的位置更新到磁盘,以确保已经持久化的数据不会丢失。

  5. Crash Recovery(崩溃恢复):当数据库发生崩溃或重启时,MySQL会通过读取Redo Log来恢复数据的一致性。它会按照Redo Log中的顺序,将每个事务的修改操作重新应用到数据库中,以还原数据的最新状态。

WAL技术的优点是可以提高数据库的性能和可靠性。通过将修改操作先记录到Redo Log中,可以避免频繁地写入磁盘,从而提高性能。同时,WAL技术还可以确保数据的持久性和一致性,即使在系统崩溃或断电的情况下也能够恢复数据。

MySQL中的WAL技术通过使用Redo Log和预写式日志的机制,确保事务的修改操作能够持久化到磁盘并保持数据的一致性。它是一种提高性能和可靠性的重要技术。

Redo log执行流程

  1. 当一个事务开始时,MySQL会为该事务分配一个唯一的事务ID,并将该事务的相关信息存储在内存中的事务控制块(Transaction Control Block,TCB)中。

  2. 在事务执行过程中,所有的修改操作都会被写入redo log缓冲区。这些修改操作包括插入、更新和删除等操作。

  3. 当事务提交时,MySQL会将该事务的所有修改操作按照顺序写入redo log文件中。这些修改操作会被写入到redo log缓冲区,然后通过后台线程定期将缓冲区中的内容刷新到磁盘上的redo log文件中。这个过程称为redo log的刷新。

  4. 在事务提交之前,MySQL会将redo log的刷新操作和数据页的刷新操作进行协调,以保证数据的一致性。这是通过使用write-ahead logging(预写式日志)的机制来实现的。即在事务提交之前,redo log必须先写入磁盘,然后再将修改操作应用到数据库中。

  5. 当数据库发生崩溃或重启时,MySQL会在启动过程中读取redo log文件,并将其中的修改操作重新应用到数据库中,以恢复数据的一致性。这个过程称为崩溃恢复。

Write Pos和CheckPoint

在MySQL的redo log中,有两个重要的概念:write pos(写入位置)和checkpoint(检查点)。

  1. Write Pos(写入位置):Write Pos是指当前事务写入redo log的位置。当一个事务提交时,其修改操作会被写入redo log中的某个位置,Write Pos指向这个位置。下一个事务的修改操作将会从Write Pos指向的位置开始写入。

  2. Checkpoint(检查点):Checkpoint是指一个标记点,表示在这个点之前的所有事务已经持久化到磁盘。当一个事务提交时,它的修改操作会被写入redo log,并且会更新Checkpoint的位置。这样,在Checkpoint之前的redo log中的操作可以被认为是已经持久化到磁盘的。

Checkpoint的作用是用于数据库的恢复和崩溃恢复。当数据库发生崩溃或重启时,MySQL会从Checkpoint的位置开始,读取redo log中的操作,并将其应用到数据库中,以还原数据的一致性。

Write Pos和Checkpoint之间的关系是,Write Pos会不断向前移动,指向最新的写入位置,而Checkpoint会根据一定的策略进行更新,以标记已经持久化到磁盘的操作。

需要注意的是,Write Pos和Checkpoint的位置是相对于redo log文件的偏移量,而不是绝对的字节位置。它们的值通常以字节为单位,表示相对于redo log文件起始位置的偏移量。

Write Pos表示当前事务写入redo log的位置,Checkpoint表示已经持久化到磁盘的操作的位置。Write Pos会不断向前移动,而Checkpoint会根据一定的策略进行更新,用于数据库的恢复和崩溃恢复。

alt

Redo log是固定大小的,超出会发生什么

当redo log的固定大小不足以容纳新的修改操作时,MySQL会触发一个称为"redo log空间不足"的错误。在这种情况下,MySQL会停止新的事务提交,直到有足够的空间来写入redo log。

为了解决redo log空间不足的问题,可以采取以下几种方法:

  1. 增加redo log的大小:可以通过修改MySQL的配置参数innodb_log_file_size来增加每个redo log文件的大小。增加redo log的大小可以提供更多的空间来存储修改操作,从而延长redo log的使用寿命。

  2. 增加redo log文件的数量:可以通过修改MySQL的配置参数innodb_log_files_in_group来增加redo log文件组中的文件数量。增加文件数量可以增加redo log的总大小,从而提供更多的空间来存储修改操作。

  3. 提交事务并清空redo log:如果当前的事务已经提交,但redo log空间不足,可以尝试手动提交其他未提交的事务,以释放redo log空间。这可以通过执行COMMIT语句来提交事务。

  4. 优化事务的写入操作:可以通过优化事务的写入操作,减少对redo log的写入量。例如,可以合并多个小事务为一个大事务,减少redo log的写入次数。

需要注意的是,增加redo log的大小或数量可能会增加系统的负载和崩溃恢复的时间。因此,在调整redo log大小时,需要综合考虑系统的性能和可靠性需求,并进行充分的测试和验证。

什么是binlog日志

Binlog(二进制日志)是MySQL的服务器层产生的一种日志,用于记录数据库中的所有修改操作,包括数据定义语言(DDL)和数据操作语言(DML)等操作。

Binlog以二进制格式记录了对数据库的逻辑修改操作,而不是直接记录对数据页的具体修改。它包含了一系列的事件(Event),每个事件都代表了一个数据库操作,如插入、更新、删除等。

Binlog的主要作用是用于「数据复制和恢复」。通过将Binlog传递给其他MySQL实例,可以实现数据的复制和同步。其他MySQL实例可以读取Binlog中的事件,并将其中的修改操作应用到自己的数据库中,从而实现数据的复制和同步。

此外,Binlog也可以用于数据恢复。在误操作、数据丢失或灾难恢复的情况下,可以通过读取Binlog来还原数据。通过逐个回放Binlog中的事件,可以将数据库恢复到特定的时间点或特定的操作之前的状态。

Binlog是追加写入的,不会被重复使用,以保留完整的修改历史。它可以通过配置参数进行启用和配置,包括指定Binlog的存储位置、设置Binlog的大小和保留时间等。

为什么MySQL会有两个日志,redo log和binlog?

MySQL之所以同时使用redo log和binlog两个日志,是因为它们具有不同的功能和用途。

  1. Redo Log(重做日志):

    • 功能:Redo log是InnoDB存储引擎特有的日志,用于保证事务的持久性和一致性。它记录了数据库中发生的修改操作,包括插入、更新和删除等操作。
    • 作用:在数据库崩溃或重启时,通过读取redo log来恢复数据的一致性。它可以将未持久化到磁盘的修改操作重新应用到数据库中,以还原数据的最新状态。
    • 特点:redo log是 「物理日志」,记录了对数据页的具体修改操作。它是循环写入的,可以重复使用,以减少磁盘IO的开销。
  2. Binlog(二进制日志):

    • 功能:Binlog是MySQL的服务器层产生的日志,记录了数据库中的所有修改操作,包括数据定义语言(DDL)和数据操作语言(DML)等操作。
    • 作用:Binlog主要用于数据复制和恢复。它可以被其他MySQL实例读取,并将其中的修改操作应用到自己的数据库中,实现数据的复制和同步。同时,Binlog也可以用于数据恢复,例如在误操作或数据丢失时,可以通过读取Binlog来还原数据。
    • 特点:Binlog是 「逻辑日志」,记录了对数据的逻辑修改操作。它是追加写入的,不会被重复使用,以保留完整的修改历史。

redo log保证了事务的持久性和一致性,而binlog则提供了数据复制和恢复的功能。它们共同工作,确保了MySQL数据库的数据安全和可靠性。

举一个例子

mysql> update T set c=c+1 where ID=2;
  1. 执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
  2. 执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
  3. 引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
  4. 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。
  5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。
update 语句执行流程
update 语句执行流程

最后三步看上去有点“绕”,将 redo log 的写入拆成了两个步骤:prepare 和 commit,这就是"两阶段提交"。

MySQL中的两阶段提交

在MySQL中,redo log和binlog是两个不同的日志文件,它们都用于确保数据的一致性和持久性。它们的写入顺序和提交顺序有所不同。

  1. Redo Log(重做日志):

    • Redo log是MySQL用于崩溃恢复的机制,它记录了事务对数据库所做的修改操作。
    • 当事务执行时,MySQL首先将修改操作记录到redo log中,然后将其写入磁盘。
    • 这样做的目的是为了在系统崩溃时,能够通过redo log来恢复未完成的事务,保证数据的一致性。
  2. Binlog(二进制日志):

    • Binlog是MySQL用于数据复制和恢复的机制,它记录了数据库的修改操作。
    • 当事务提交时,MySQL将修改操作记录到binlog中,但不立即写入磁盘。
    • Binlog的写入是异步的,可能会有一定的延迟。

现在来解释为什么MySQL先写redo log,然后等binlog写完后才提交:

  1. 事务的持久性和恢复能力:

    • 通过将修改操作记录到redo log中,MySQL可以确保即使系统崩溃,也能够通过redo log来恢复未完成的事务,保证数据的一致性。
    • 因此,redo log的写入是在事务执行期间进行的,以提供更好的性能。
  2. 数据复制和恢复:

    • Binlog用于数据复制和恢复,它记录了所有的数据库修改操作。
    • 在事务提交之后,MySQL将修改操作记录到binlog中,以供主从复制等场景使用。
    • 为了保证数据的一致性,MySQL会等待binlog的写入完成,然后才提交事务。

所以,MySQL先写redo log,然后等binlog写完后才提交的目的是为了「保证数据的一致性和持久性」「并提供数据复制和恢复的能力」。这样的设计可以提高性能,并确保在系统崩溃或数据复制场景下的数据完整性。希望这次解释更加清晰明了。如果还有任何疑问,请随时提问。

没写完发生Crash了会出现什么情况?

仍然用前面的 update 语句来做例子。假设当前 ID=2 的行,字段 c 的值是 0,再假设执行 update 语句过程中在写完第一个日志后,第二个日志还没有写完期间发生了 crash,会出现什么情况呢?

  1. 「先写 redo log 后写 binlog」。假设在 redo log 写完,binlog 还没有写完的时候,MySQL 进程异常重启。由于我们前面说过的,redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行 c 的值是 1。但是由于 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。然后你会发现,如果需要用这个 binlog 来恢复临时库的话,由于这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 c 的值就是 0,与原库的值不同。
  2. 「先写 binlog 后写 redo log」。如果在 binlog 写完之后 crash,由于 redo log 还没写,崩溃恢复以后这个事务无效,所以这一行 c 的值是 0。但是 binlog 里面已经记录了“把 c 从 0 改成 1”这个日志。所以,在之后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 c 的值就是 1,与原库的值不同。

可以看到,如果不使用“两阶段提交”,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致。

本文由 mdnice 多平台发布

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

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

相关文章

语言基础篇14——Python源文件组织结构,模块与包、命名空间与作用域的奥秘

源文件组织结构 模块与包 模块,module 一个文件,包含Python源码,以.py为后缀 包,package 结构化模块,一个文件夹,包含__init__.py文件、若干.py文件和若干文件夹 module对象 模块和包被导入后为modu…

保姆级-微信小程序开发教程

一,注册微信小程序 如果你还没有微信公众平台的账号,请先进入微信公众平台首页,点击 “立即注册” 按钮进行注册。注册的账号类型可以是订阅号、服务号、小程序以及企业微信,我们选择 “小程序” 即可。 接着填写账号信息&#x…

洗衣洗鞋小程序干洗店洗衣店上门取衣门店管理系统开发定制

校园洗衣洗鞋软件是一款非常优质的校园洗护服务软件,软件功能非常强大,学生们可以通过软件预约洗衣服务,支持上门取送,还能够浏览洗衣产品商城,操作非常便捷,感兴趣的朋友快来体验吧! 后台管理…

开发板插入sd/tf卡后自动挂载

测试平台-hisi-dv500 要在Linux系统上实现TF卡(Micro SD卡)插入后自动挂载,类似于SD卡/TF卡插入也会触发内核事件,你可以使用udev工具来监控并处理这些事件,创建一个udev规则文件来捕获TF卡插入事件. 1:创建一个udev规则文件,例…

飞书即时消息无需API开发连接Cohere,打造飞书AI智能问答助手

飞书即时消息用户使用场景: 许多企业都在使用飞书系统进行协同办公,而现在有了Cohere大语言模型技术,能够根据用户的提问来自动产生回答,无需人为干预。对于企业负责人来说,他们认为如果将Cohere技术融入到飞书机器人中…

SpringBoot+jSerialComm实现Java串口通信 读取串口数据以及发送数据

记录一下使用SpringBootjSerialComm实现Java串口通信,使用Java语言开发串口,对串口进行读写操作,在win和linux系统都是可以的,有一点好处是不需要导入额外的文件。 案例demo源码:SpringBootjSerialComm实现Java串口通信 读取串口…

easypoi导入数值精度丢失

记录一下easypoi导入数值,精度丢失的解决方案 1.导入的excel字段如图 2.easypoi解析CellValueService部分源码: 这个方法拿到的原始数据如图: 解决方法: 1.统一处理方式:在解析的时候使用DecimaFormat进行数据格式化 //格式化为6为小数 De…

Day57|leetcode 647. 回文子串、516.最长回文子序列

leetcode 647. 回文子串 题目链接:647. 回文子串 - 力扣(LeetCode) 视频链接:动态规划,字符串性质决定了DP数组的定义 | LeetCode:647.回文子串_哔哩哔哩_bilibili 题目概述 给你一个字符串 s ,…

使用动态住宅代理还能带来哪些好处?

一、什么是动态住宅代理ip 动态住宅代理是一种代理技术,它利用代理服务器中转用户和目标服务器之间的网络流量,实现用户真实位置的屏蔽。代理提供商会有自己的ip大池子,当你通过代理服务器向网站发送请求时,服务器会从池子中选中…

Spring系列文章:Spring6集成MyBatis3.5

1、引入依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.2</version></dependency><dependency><groupId>org.mybatis</groupId><artif…

jsp页面出现“String cannot be resolved to a type”错误解决办法

篇首语&#xff1a;小编为大家整理&#xff0c;主要介绍了jsp页面出现“String cannot be resolved to a type”错误解决办法相关的知识&#xff0c;希望对你有一定的参考价值。 jsp页面出现“String cannot be resolved to a type”错误解决办法 解决办法&#xff1a; 右键项目…

软考高级架构师下篇-14面向服务架构设计理论

目录 1. 引言2. SOA的相关概念3. SOA的发展历史4. SOA的参考架构5. SOA 主要协议和规范6. SOA设计的标准要求7. SOA的作用与设计原则8. SOA的设计模式9. SOA构建与实施10. 前文回顾1. 引言 在面向服务的体系结构(Service-Oriented Architecture,SOA)中,服务的概念有了延伸…

详解:API开发【电商API封装商品数据SKU接口的开发接入】

电商API开发8.1 RESTful API的设计8.2 API的路由和控制器8.3 API的认证和授权 RESTful API的设计 RESTful API是一种通过HTTP协议发送和接收数据的API设计风格。它基于一些简单的原则&#xff0c;如使用HTTP动词来操作资源、使用URI来标识资源、使用HTTP状态码来表示操作结果等…

Java多线程(四)锁策略(CAS,死锁)和多线程对集合类的使用

锁策略&#xff08;CAS&#xff0c;死锁&#xff09;和多线程对集合类的使用 锁策略 1.乐观锁VS悲观锁 2.轻量级锁VS重量级锁 3.自旋锁VS挂起等待锁 4.互斥锁VS读写锁 5.可重入锁vs不可重入锁 死锁的第一种情况 死锁的第二种情况 死锁的第三种情况 CAS 1.实现原子类 …

苹果发布会:iPhone15系列

苹果将在北京时间9月13日凌晨1点召开发布会&#xff0c;本次发布会的主角是iPhone 15系列&#xff0c;包含四款机型&#xff1a;iPhone 15、iPhone 15 Plus、iPhone 15 Pro 以及 iPhone 15 Pro Max&#xff0c;本次发布会快科技全程视频直播&#xff0c;有关产品的细节也会在新…

四川百幕晟科技:抖音新店怎么快速起店?

抖音作为全球最大的短视频平台&#xff0c;拥有庞大的用户基础和强大的影响力&#xff0c;成为众多商家宣传产品、增加销量的理想选择。那么&#xff0c;如何快速开店并成功运营呢&#xff1f;下面描述了一些关键步骤。 1、如何快速开新店&#xff1f; 1、确定产品定位&#x…

系列一、前言

本系列文章是参考B站尚硅谷老师讲的 "尚硅谷Nginx教程由浅入深&#xff08;一套打通丨初学者也可掌握&#xff09;"系列课程&#xff0c;然后结合自己真实的操作而总结的系列文章。我也把自己学习、实操过程中的详细笔记以脑图的形式分享了出去&#xff0c;发现大家对…

SpringMVC实战crud增删改查

一.公共页面的跳转 1.编写页面跳转控制类 package com.YU.web;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping;/*** author YU* create …

Apache Linki 1.3.1+DataSphereStudio+正常启动+微服务+端口号

我使用的是一键部署容器化版本&#xff0c;官方文章 默认会启动6个 Linkis 微服务&#xff0c;其中下图linkis-cg-engineconn服务为运行任务才会启动,一共七个 LINKIS-CG-ENGINECONN:38681 LINKIS-CG-ENGINECONNMANAGER:9102 引擎管理服务 LINKIS-CG-ENTRANCE:9104 计算治理入…

Linux 中的 chpasswd 命令及示例

chpasswd命令用于更改密码,尽管passwd命令也可以执行相同的操作。但它一次更改一个用户的密码,因此对于多个用户,使用chpasswd 。下图显示了passwd命令的使用。使用passwd我们正在更改来宾用户的密码。首先,您必须输入当前签名用户的密码,然后更改任何其他用户的密码。必须…