糟了,数据库崩了,又好像没崩

2023-12-05

前言

2023 年某一天周末,新手程序员小明因为领导安排的一个活来到公司加班,小明三下五除二,按照领导要求写了一个跑批的数据落库任务在测试环境执行 ,突然间公司停电了,小明大惊,“糟了,MySQL 还在跑任务,会不会因为突然断电,导致数据库崩了”。

这时候,傍边的同事云淡风清的说了一句,“没事,小明,MySQL 有一套预写日志机制就是应对这种情况的。你的落库任务启用了事务没,启用了的话,就等来电重新跑一下任务就行了。”

听了同事的话,小明悬着的心放了下来。 “哦哦,我启用了事务,那我还是等周一来重新跑一遍”。

回家的公交车上,小明默默的打开百度,搜索 MySQL 预写日志 ,写下了这篇文章 ????。

本文思维导图

本文思维导图

什么是预写日志机制?

一般情况下,大部分数据库都是将表和索引存储在磁盘文件中。当新增数据时,数据库系统会先写入内存,然后将其写入磁盘上的数据文件。

那为什么不直接写入磁盘嘞?主要是每次新增都直接写入磁盘性能很低,放在内存中,可以批量写入磁盘以提升性能。

但有一个问题,如果数据在写入磁盘文件中途断电怎么办?当来电恢复后,我们重启数据库,发现数据不一致,又该如何处理。

所以我们需要一些其他机制来避免断电引发的数据不一致,其实 MySQL 已经考虑到了这一点,内部已经实现一套 WAL(预写日志)机制来避免这一点。

MySQL 设计有健壮的恢复机制,特别是使用 InnoDB 存储引擎的情况下,它能够在断电后重启而不会崩溃。InnoDB 存储引擎使用预写日志(WAL)机制来确保数据的一致性和原子性。

预写日志机制是一种数据库事务日志技术,它要求在任何数据库修改被写入到永久存储(也就是磁盘)之前,先将这些修改记录到日志中。

这样当 MySQL 遇到意外的断电情况时,它会在重启后利用 Redo log 来恢复已提交但未写入数据文件的事务继续写入数据文件,从而保证一致性,再利用 undo log 来撤销未提交事务的需改,从而保证原子性。

MySQL 中的预写日志机制

在 MySQL 中,InnoDB 存储引擎实现了 WAL 机制。包含 Redo log buffer、Redo log、Undo Log 等,来记录事务已提交但未写入数据文件的数据变更以及事务回滚后的数据还原。

为了给大家讲清楚 MySQL 的预写日志机制,会涉及到 MySQL 架构中的以下内容,

Buffer Pool(缓冲池)

Buffer Pool (缓冲池)是 InnoDB 存储引擎中非常重要的内存结构,顾名思义,缓冲池就是起到一个缓存的作用,因为我们都知道 MySQL 的数据最终是存储在磁盘中的,如果没有这个 Buffer Pool 那么我们每次的数据库请求都会磁盘中查找,这样必然会存在 IO 操作,这肯定是无法接受的。

但是有了 Buffer Pool 就是我们第一次在查询的时候会将查询的结果存到 Buffer Pool 中,这样后面再有请求的时候就会先从缓冲池中去查询,如果没有再去磁盘中查找,然后在放到 Buffer Pool 中。

Redo log buffer(日志缓冲区)

Redo log buffer 是用作数据变更记录写入 Redo log 文件前的一块内存区域。日志缓冲区大小由 innodb_log_buffer_size 变量定义,默认大小为 16MB。

日志缓冲区的内容会定期刷新到 Redo log 文件中,大型日志缓冲区允许大型事务运行,而无需在事务提交之前将 Redo log 数据写入磁盘。因此如果事务涉及的更新、插入或删除操作数据量较大时,可以增加日志缓冲区的大小可以节省磁盘 I/O。

MySQL 提交事务的时候,会将 Redo log buffer 中的数据写入到 Redo log 文件中,刷磁盘可以通过 innodb_flush_log_at_trx_commit 参数来设置

  • 值为 0 表示不刷入磁盘

  • 值为 1 表示立即刷入磁盘

  • 值为 2 表示先刷到 os cache

为了提高性能,MySQL 首先将修改操作写入到日志缓冲区,之后以 innodb_flush_log_at_trx_commit 参数设置落盘时机,将日志缓冲区刷入到磁盘的 Redo log 文件中去。

Redo Log

MySQL Redo Log 是 InnoDB 存储引擎中的一个重要组件,它是一种磁盘基础的数据结构,用于在崩溃重启期间修复由已提交事务但未写入数据文件的数据。

在正常操作中,Redo log 记录了由 SQL 语句执行导致的表数据变更记录。将 Redo log buffer 中的数据持久化到磁盘中,就是将 Redo log buffer 中的数据写入到 Redo log 磁盘文件中。

数据在由 Redo log buffer 写入 Redo log 时的触发时机如下,

  • MySQL 正常关闭时触发

  • 当 Redo log buffer 中记录的写入量大于 Redo log buffer 内存空间的一半时,会触发落盘

  • InnoDB 的后台线程每隔 1 秒,将 Redo log buffer 持久化到磁盘

  • 每次事务提交时都将缓存在 redo log buffer 里的 redo log 直接持久化到磁盘(这个策略就是由上文提高 innodb_flush_log_at_trx_commit 参数控制)

Redo log 是 WAL 机制的核心,它记录了事务所做的所有修改。如果数据库发生故障,可以使用 Redo 日志来重做事务,从而确保数据的一致性。

Undo Log

Undo Log 记录了如何撤销一个事务的修改。如果需要回滚事务或在执行事务时还未提交,数据库就发生了崩溃,这时我们就需要将未提交事务前的数据回滚回去,难道这个操作有我们自己来做吗?显然 MySQL 也考虑到了这一点。

MySQL 会使用 Undo log 来撤销未提交的修改。在操作数据前,MySQL 首先将数据备份到 Undo log,然后进行数据修改。

如果出现错误或者用户执行了 Rollback 语句,系统可以利用 Undo log 中的备份将数据恢复到事务操作前的状态。

通过 Undo log 撤销修改,从而确保数据的原子性。


结合 Buffer Pool、Redo log buffer、Redo log、Undo log 后,我们在 MySQL 中更新一条数据的流程 如下,

图片来源https://pdai.tech/md/db/sql-mysql/sql-mysql-execute.html

图片来源https://pdai.tech/md/db/sql-mysql/sql-mysql-execute.html

  • 准备更新一条 SQL 语句

  • MySQL(innodb)会先去缓冲池(Buffer Pool)中去查找这条数据,没找到就会去磁盘中查找,如果查找到就会将这条数据加载到缓冲池(Buffer Pool)中

  • 在加载到 Buffer Pool 的同时,会将这条数据的原始记录保存到 undo 日志文件中

  • innodb 会在 Buffer Pool 中执行更新操作

  • 更新后的数据会记录在 Redo log buffer 中

  • MySQL 提交事务的时候,会将 Redo log buffer 中的数据写入到 Redo log 文件中,刷磁盘可以通过 innodb_flush_log_at_trx_commit 参数来设置

  • MySQL 重启的时候会将 Redo log 恢复到缓冲池中

额外知识:检查点(Checkpoint)

检查点是什么?为什么有了 Redo log、Undo log 还要引入检查点。

明明借助 Redo log、Undo log 我们就可以实现 MySQL 的故障恢复了。

虽然数据在写入 Redo log 文件后,就代表数据变更已经生效了,但是还未写入到数据文件,也就是还没有完成事务的持久性。

那么检查点就是帮助 MySQL 实现事务的持久性。

如果说 Redo log 可以无限地增大,能够保存所有数据库变更的数据,那么在发生宕机时完全可以通过 Redo log 来恢复数据库系统的数据到宕机发生前的情况。

然而现实是我们的物理磁盘文件大小是有效的。即使达成无限了,如果数据库运行了很久后发生宕机,那么使用 Redo log 进行恢复的时间也会非常的久。

所以在 Redo log 文件容量是有限的情况下,还需要定期将 Redo log 写入数据文件完成数据的持久化,在这样的情况下,就引入了 Checkpoint(检查点)技术。

Checkpoint(检查点)技术不仅仅是会同步 Redo log 写入数据文件,也会同步脏页数据写入数据文件。

检查点的触发时机有两种如下,

Sharp Checkpoint(完全检查点)

将内存中所有脏页全部写到磁盘就是完全检查点,比如数据库实例关闭时。

Fuzzy Checkpoint(模糊检查点)

将部分脏页刷新到磁盘,就是模糊检查点,一般就是脏页达到一定数量时触发。数据库实例运行过程产生的检查基本上就是这种类型的检查点。

因此其实 Checkpoint 就是指一个触发点(时间点),当发生 Checkpoint 时,会将脏页写回磁盘,以确保数据的持久性和一致性。并且 Redo log、Undo log 文件也可以重新覆写,这样可以保证重启时不会因为 Redo log、Undo log 文件太大而导致重启时间过长。

断电故障恢复案例

图片来源https://www.pcworld.com/article/419101/what-to-do-when-a-power-disaster-bricks-your-pc.html

图片来源https://www.pcworld.com/article/419101/what-to-do-when-a-power-disaster-bricks-your-pc.html

OK,假如我们正在使用 MySQL 添加数据。在提交事务的过程中,突然发生了断电,那么这个数据会丢吗?

我们结合上文 MySQL 中更新一条数据的流程 ,来给大家分析下具体场景,

数据在写入 Buffer Pool、Redo log buffer 中时,发生断电

先说结论,会丢。因为数据没有写入 Redo log 前,MySQL 是没办法保证数据一致性的。但是这没关系的,因为 MySQL 会认为本次事务是失败的,在重启后可以根据 Undo log 文件将数据恢复到更新前的样子,并不会有任何的影响。

数据在写入 Redo log 文件后,发生断电

先说结论,不会丢。因为 Redo log buffer 中的数据已经被写入到 Redo log 了,就算数据库宕机了,在下次重启的时候 MySQL 也会将 Redo log 文件内容恢复到 Buffer Pool 中进行重放。

参考资料

  • https://xiaolincoding.com/mysql/log/how_update.html#redo-log-%E6%96%87%E4%BB%B6%E5%86%99%E6%BB%A1%E4%BA%86%E6%80%8E%E4%B9%88%E5%8A%9E

  • https://pdai.tech/md/db/sql-mysql/sql-mysql-execute.html

  • https://zhuanlan.zhihu.com/p/552706911?utm_medium=referral

最后说两句

预写日志机制是数据库管理系统中保证数据安全性的关键技术。在 MySQL 中,通过 InnoDB 存储引擎实现的 WAL 机制,即使在发生断电等意外情况下,也能够有效地保护数据不受损坏。这使得 MySQL 成为了一个可靠和健壮的数据库解决方案,适用于各种需要高数据一致性和可靠性的应用场景。

关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、国外优质文章翻译等,您的关注将是我的更新动力!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

糟了,数据库崩了,又好像没崩 的相关文章

随机推荐

  • Nessus简单介绍与安装

    1 Nessus简介 Nessus号称是世界上最流行的漏洞扫描程序 全世界有超过75000个组织在使用它 该工具提供完整的电脑漏洞扫描服务 并随时更新其漏洞数据库 Nessus不同于传统的漏洞扫描软件 Nessus可同时在本机或远端上遥控
  • WebGL笔记:矩阵平移的数学原理和实现

    矩阵平移的数学原理 让向量OA位移 x方向 tx y方向 ty z方向 tz 最终得到向量OB 矩阵平移的应用 再比如我要让顶点的x移动0 1 y移动0 2 z移动0 3 1 顶点着色器核心代码
  • 有效表达观点的艺术

    有效表达观点的艺术 在人际交往中 有效地表达自己的观点是建立良好关系和实现有效沟通的关键 然而 这并不总是易如反掌 有时候 我们可能会遇到表达困难 或者我们的观点可能被误解 本文将探讨如何有效地表达观点 以及掌握说话的艺术的重要性 首先 清
  • 人工智能:开启未来商业新篇章

    人工智能 开启未来商业新篇章 随着科技的快速发展 人工智能 AI 在商业领域的应用越来越广泛 成为企业把握未来商业机遇的重要方向 本文将探讨人工智能如何重塑商业格局 为企业提供新的增长点 以及企业如何抓住AI的商业契机 一 AI重塑商业格局
  • 机器人学英语

    我的prompt i want to you act as an english language teacher asistant to help me study english you could teach me in such a
  • 详解Hotspot的经典7种垃圾收集器原理特点与组合搭配

    详解Hotspot的经典7种垃圾收集器原理特点与组合搭配 HotSpot共有7种垃圾收集器 3个新生代垃圾收集器 3个老年代垃圾收集器 以及G1 一共构成7种可供选择的垃圾收集器组合 新生代与老年代垃圾收集器之间形成6种组合 每个新生代垃圾
  • 在深圳月入一万的很丢人吗

    在深圳 月入一万的收入是否丢人 这是一个很主观的问题 因为每个人的生活需求和价值观不同 从经济学的角度来看 深圳作为中国的经济特区和一线城市 其生活成本相对较高 从这个角度看 月入一万的收入在某种程度上可能不足以满足一些人的生活需求 根据最
  • 给自己泡了一壶茶

    清晨 当第一缕阳光透过窗户照亮了房间 我慵懒地爬起床 开始享受新的一天 我泡了一壶早茶 浅浅的茶香立刻弥漫在空气中 让我感到宁静而放松 我坐在窗边 静静地看着窗外的世界 清晨的街道上 行人和车辆都还不多 显得格外的宁静 微风吹过树叶 带来阵
  • 拍图识字软件哪个好用?这些好用的软件推荐给你们

    在快节奏的现代生活中 你可能会遇到需要从图片中获取文字信息的情况 无论是读书 工作还是生活中 有时候会需要从图片中提取文字 当你收到了一份手写的便签或菜单 上面的字迹可能很模糊 或者你需要在没有文字的地方快速获取信息 这时 你可能会想 如果
  • 详解十大经典排序算法(四):希尔排序(Shell Sort)

    算法原理 希尔排序是一种基于插入排序的排序算法 也被称为缩小增量排序 它通过将待排序的序列分割成若干个子序列 对每个子序列进行插入排序 然后逐步缩小增量 最终使整个序列有序 算法描述 希尔排序 Shell Sort 是一种基于插入排序的算法
  • 使用tensorrt加速深度学习模型推断

    使用tensorrt加速深度学习模型推断 1 import以及数据加载 构建engine函数 2 导入官方模型及CIFAR100数据集 3 不采用tensort的推断时间 4 采用tensort加速 使用tensorrt 库 4 1 导出o
  • 京东商品详情接口在电商行业中的重要性及实时数据获取实现

    一 引言 随着电子商务的快速发展 商品信息的准确性和实时性对于电商行业的运营至关重要 京东作为中国最大的电商平台之一 其商品详情接口在电商行业中扮演着重要的角色 本文将深入探讨京东商品详情接口的重要性 并介绍如何通过API实现实时数据获取
  • 城市化人群隔离悖论

    城市是人群大规模聚集的过程 表面上似乎会提高人与人之间相互接触和交往的效率 但不可思议的是 美国学者的研究发现 城市越大 人和人之间相互隔离越严重 这显然是违背直觉的现象 反直觉往往意味着新发现 就给这种现象命名为城市化人群隔离悖论吧 这是
  • 未来已来,AI与情报分析,是黑暗或光明?

    这篇文章有点像一个实验 在乔治城大学 Georgetown University 举行的 负责任的人工智能和情报 Responsible AI and Intelligence 会议上 ChatGPT被要求撰写一篇文章 陈述关于我将如何评估
  • 外卖小程序需要多大云服务器?

    外卖小程序是一种基于互联网技术实现的餐饮电商平台 具有实时配送 快速响应和跨地区订餐等特点 为保证外卖小程序在高并发和业务繁忙的情况下能够稳定运行 需要具备一定的云服务器配置 具体也有考虑公司业务规模大小 用户量 原文地址 外卖小程序需要多
  • 服务器2g内存个人使用可以吗?

    对于个人日常使用而言 云服务器2G内存是足够的 一般来说 对于普通用户而言 使用云服务器主要是用来搭建网站 存储文件和数据备份等基本操作 虽然这些操作看似比较简单 但是实际上还是需要一定的计算资源才能完成的 原文地址 服务器2g个人使用可以
  • 淘宝商品详情接口在电商运营中的应用实例

    一 背景 某电商企业A在运营过程中 发现手动更新商品信息效率低下 且容易出现信息不一致的情况 为了解决这个问题 企业A决定采用淘宝商品详情接口 实现商品信息的自动获取和更新 二 目标 通过集成淘宝商品详情接口 企业A希望实现以下目标 自动获
  • Latex公式中矩阵的方括号和圆括号表示方法

    一 背景 在使用Latex写论文时 不可避免的涉及到矩阵公式 有的期刊要求矩阵用方括号 有的期刊要求矩阵用圆括号 因此 特记录一下Latex源码在两种表示方法上的区别 以及数组和方程组的扩展 二 矩阵的方括号表示 首先所有的矩阵肯定都是在标
  • Python机器学习、深度学习入门丨气象常用科学计算库、气象海洋常用可视化库、爬虫和气象海洋数据、气象海洋常用插值方法、EOF统计分析、WRF模式后处理等

    目录 专题一 Python软件的安装及入门 专题二 气象常用科学计算库 专题三 气象海洋常用可视化库 专题四 爬虫和气象海洋数据 专题五 气象海洋常用插值方法 专题六 机器学习基础理论和实操 专题七 机器学习的应用实例 专题八 深度学习基础
  • 糟了,数据库崩了,又好像没崩

    前言 2023 年某一天周末 新手程序员小明因为领导安排的一个活来到公司加班 小明三下五除二 按照领导要求写了一个跑批的数据落库任务在测试环境执行 突然间公司停电了 小明大惊 糟了 MySQL 还在跑任务 会不会因为突然断电 导致数据库崩了