这段时间对mysql数据库事务的acid做了一些深入的研究,理解了如何在异常情况下保证事务的acid。而最严重的异常情况莫过于断电,随时都有可能发生且发生时不会有任何保存的机会,所以就想以事务处理的各个阶段发生断电的情况下mysql如何保证acid为切入点总结一下这段时间所学到的东西。

概述

这段时间对mysql数据库事务的acid做了一些深入的研究,理解了如何在异常情况下保证事务的acid。而最严重的异常情况莫过于断电,随时都有可能发生且发生时不会有任何保存的机会,所以就想以事务处理的各个阶段发生断电的情况下mysql如何保证acid为切入点总结一下这段时间所学到的东西。

本文将重点介绍commit命令执行的各个阶段,mysql是如何进行断电恢复的。

mysql的page、日志和buffer介绍

page

mysql的page与文件系统的block类似,是mysql自己定义的读取和写入磁盘的最小单位,其目的是为了充分的利用磁盘的顺序访问速度快的优势。一般是磁盘扇区的4~16倍。

logsundolog。即 mvcc 历史快照,记录的是某行过去的某个版本,用于帮助事务回滚及 MVCC 的功能。存储在表空间,以 transaction 为维度记录,且记录了 transaction 状态 ,可用于 crash 恢复时提取未提交的事务。可以理解成一张特殊的表,也会用到 buffer pool 。

redolog。可以理解为内存数据的WAL(write-ahead-log),用来恢复未flush到disk的page数据。记录的是对页的二进制级别的修改操作,比如某个偏移写入'aa'记录。一般存储在单独的redo log文件中,数据库全局的。另外要注意的是, undolog 的写入也会生成对应的 redo log 。

binlog。即我们常说的二进制日志,主要用于主从复制。

bufferbuffer pool。即 mysql page 的 buffer 。使用 lru 来管理。

doublewrite buffer。在 flush page 到磁盘之前,会先将 page 写入这里,为了防止 page flush 到一半时断电造成的磁盘 page 数据不完整的问题。存储介质虽为文件,但充分利用顺序写,所以很快。

log buffer。即 redolog 的内存 buffer 。 用于降低 redolog 对于写入速度的影响。

除了这些还有 change buffer 等,不影响接下来的内容介绍,故不在此处展开讨论。

mysql写入过程简介

commit 之前

先说说 commit 命令之前,写入操作对应的过程。 此时所有的写入操作都会通过 undolog 的支持,同时保留写入之前的版本和写入之后的版本,而这里对表数据和 undolog 的修改并不会直接写入到磁盘中,而是写入 buffer pool 中,同时生成相应的 redolog 。而此时的 redolog 存放在 log buffer 中,这样做的目的是为了减少 redolog 对写入性能的影响。想象一下,如果每次写入产生的 redolog 都写入磁盘,即使是顺序写入,也会造成不小的影响。所以,如果一个 transaction 中包含大量的写入操作,最好将 log buffer 调大一些,避免不必要的磁盘 io 。 下面说说 commit 的执行过程。由于在生产环境中,绝大多数 mysql 实例都会开启 binlog ,因此我们主要介绍开启 binlog 时 commit 的实行过程。

commit 执行过程

在开启 binlog 的情况下, mysql 使用 2PC 来执行 commit 过程,具体步骤如下: * 阶段1:将 undolog 中的 transaction 状态改为 prepared ,并生成相应的生成 redolog ,然后 flush log buffer 。 * 阶段2:将 transaction 写入 binlog ,然后告诉底层存储引擎将 undolog 中的 transaction 状态改为 commited 并生成 redo log 。只要写入binlog成功,就可以认为事务写入成功。

另外需要注意的是,此时 mysql 使用 xid 来标识该事务。

断电恢复过程

完成了 prepare 阶段,写入 binlog 之前断电

这种情况下, mysql 重新启动时,会从 redolog 中读出未 flush 到磁盘中的 page —— buffer pool 。然后从 redolog 重建这些内存中的 page ,以恢复断电之前内存的状态。之后,mysql检测到该事务并未提交,因此主动执行事务的回滚操作。

flush buffer pool 时断电

即 flush page 的时候。此时造成 page 一部分数据写入磁盘,另一部分数据未写入磁盘。这时无法从 redo log 恢复异常 page 。原因是:之前提到 redo log 保存的page的修改记录,即从原 page 到新 page 的 patch ,而此时原 page 已经丢失(因为 page 的一部分数据已经写入磁盘),所以无法从 redo log 恢复。这时就要用到 double write buffer 了。每次 flush page 之前,都会先将 page flush 到一个 double write buffer ,如果在真正 flush page 的时候出现异常,则可以从 double write buffer 恢复这个 page 。

flush log buffer 时断电

即 redolog 的flush。由于 redolog 的 flush 是以扇区为单位进行 flush 的,而扇区的写入是原子性的(当代的大部分硬盘都有这个能力),因此不会造成部分写入、部分未写入的情况。

写完 binlog 后断电

上面说到,写入binlog时,便可认为事务提交成功,就可以保证acid中的d。此时如果断电,mysql在启动会执行如下过程: 1. 先从binlog中筛选出所有xid并创建hash_list 2. 然后从存储引擎(如innodb)中选出prepared状态的transaction的xid列表list。一般是从rollback segments(rseg) —— undo log ——中提取xid列表,然后在选出prepared状态的。 3. 遍历list的xid,如果xid在hash_list中则commit,否则rollback。

写入 binlog 时断电

binlog 的写入也是没有 double write buffer 保护的,那么在写入 binlog 的过程中如果发生了断电, mysql 是如何恢复的呢。如上面介绍的写入 binlog 后断电恢复过程所示, mysql 会从 binlog 中选出所有的 xid 并创建恢复列表,不过在遍历 binlog 的过程中, mysql 同时也会寻找 last valid position ,并将这个 position 之后的内容都截取掉。因此,如果某个 transaction 写入 binlog 的过程中断电,并且有一部分未成功写入,则该 transaction 在 mysql 重启时会被回滚。

相关配置

这些配置是mysql5.7之后的默认配置:

* sync_binlog=1 * innodb_support_xa=ON * innodb_flush_log_at_trx_commit=1。用于控制 log buffer 的刷新时机。

参考资料

mysql 断电_mysql的断电恢复能力相关推荐

  1. mysql经常断电_MySQL突然断电异常解决

    线上正在运行的Mysql,因为突然断电而引发一系列错误! 重启开机执行命令启动数据库 # /etc/init.d/mysqld start Starting MySQL.The server quit ...

  2. mysql数据库断电_MySQL 数据库忽然断电会丢数据吗转载

    在上一章,我讲解了 MySQL 锁的相关内容.主要谈到了全局锁.表锁.行锁以及死锁等.通过这些学习,相信我们可以理解锁的原理,并在工作中降低锁冲突的概率.这也是优化数据库必须掌握的知识点. 从本节开始 ...

  3. mysql停电_MySQL断电后报错处理

    文章目录 前言 后记 前言 问题保留,如果有大佬会可以留言教我一下! 因为做的cacti没有做完,回家的时候就将电脑从休眠状态起不来.于是我就断电重启.自此mysql就不正常了,一直出现报错.因为之前 ...

  4. 记一次mysql主从同步因断电产生的不能同步问题 1236 and 1032

    背景: 项目新上线一个月,qa需要测试断电服务拉起,服务拉起成功后,发现mysql主从异常 以下是发现的问题以及解决方案 问题1: Slave_IO_Running:  No 一方面原因是因为网络通信 ...

  5. mysql断电同步不起作用_记一次mysql主从同步因断电产生的不能同步问题 1236 and 1032...

    背景: 项目新上线一个月,qa需要测试断电服务拉起,服务拉起成功后,发现mysql主从异常 以下是发现的问题以及解决方案 问题1: Slave_IO_Running:  No 一方面原因是因为网络通信 ...

  6. mysql 修复_mysql修复表的三个方法

    断电或非正常关机可能导致MySQL数据库出现表损坏,特别是MyISAM表数据很大的时候.有三种方法,一种方法使用MySQL的repair table的sql语句,另一种方法是使用MySQL提供的myi ...

  7. mysql语句_Mysql语句

    ------------恢复内容开始------------ 存储引擎 存储引擎是用于根据不同的机制处理不同的数据. 查看mysql中所用引擎: show engines: create table ...

  8. php mysql修复_MySQL数据表损坏的巧妙修复

    此文章主要向大家描述的是正确修复损坏的MySQL数据表的实际操作流程,我们大家都知道断电或者非正常关机往往会导致MySQL(和PHP搭配之最佳组合)数据库出现错误.其主要有两种方法: 一种方法使用My ...

  9. mysql提交事务_mysql事务的实现原理

    此篇文章算是对mysql事务的一个总结,基本把mysql事务相关的知识点都涵盖到了,面试问来问去无非也就是这些,在了解这些之前我们先对mysql在执行的过程中有一个整体的认识,如下图 如上图所示,My ...

最新文章

  1. python timestamp转string_Python操作钉钉机器人发送各种消息
  2. 云视频会议的“多、快、好、省”(下)
  3. 短线王的盯盘宝怎么样_2022考研英语韦林全程班怎么样?资源分享
  4. java 基础知识巩固_Java基础巩固——《Java核心技术基础·卷一:基础知识》
  5. Python FastApi:快速建立docker容器/挂载共享文件夹/导入导出
  6. ClickOnce Cannot download the application解决方法
  7. struts2 中的 addActionError 、addFieldError、addActionMessage方法的区别添加错误信息
  8. python37安装失败怎么搞_Linux 安装Python37
  9. java递归算法的实例最细讲解
  10. mysql:Prepared statement needs to be re-prepared解决办法
  11. python分号_python分号_python 分号_python加分号 - 云+社区 - 腾讯云
  12. 音乐处理原理第一章:音乐表示
  13. 【BZOJ3872】Ant colony(二分,动态规划)
  14. 计算机输入密码不满足密码策略,密码不满足密码策略的要求windowsserver2008/2012...
  15. C++ primer 第五版 练习题记录
  16. Hibernate3与EJB3的关系
  17. Cache与Scratch-pad-memory(spm)的区别
  18. 编写一个python程序用来计算投资回收期_程序设计基础(Python)超星尔雅章节答案...
  19. 压缩包忘记密码怎么解压
  20. Python文件的读写、正则表达式的运用、多线程与多进程、网络编程

热门文章

  1. 2012软件下载排行榜最新版下载地址:flashfxp VS竞技游戏平台 酷我音乐
  2. vscode连接电脑虚拟机上的ubuntu
  3. 数据结构基本操作总结(C语言版)---链表、栈与队列
  4. 微信小程序使用全套指南
  5. 计算机在教育的应用,计算机技术在教育中的应用
  6. MySQL正确配置my.ini的event_scheduler = ON
  7. win10将搜索栏缩小
  8. 信息安全实训周——五月四日学习记录
  9. DELL 准备开始拉拢MS了咩
  10. QMainWindow