MySQL的undo/redo日志和binlog日志,以及2PC
发现自己的知识点有点散,今天就把它们连接起来,好好总结一下。
一、undo log、redo log、binlog的定义和对比
| 定义和作用 | 所在架构层级 | 日志形式 | 所在文件和默认名称,组织结构 | 是否缓存,如何缓存 | 写文件方式 | |||
| undo log |
回滚日志,在事务执行的过程中操作任何数据之前先将数据备份到undolog中。 事务失败时可根据undo log进行回滚。 用来保证事务的一致性。 还可以用来实现多版本并发控制MVCC。 |
InnoDB引擎层 | 逻辑日志,以行的形式进行记录。 |
共享表空间文件,ibdata0/ibdata1。 undo只是该文件的的一部分(rollback segment),文件由页组成,每一页又由一行行的数据组成,undo相对有自己的固定页,会循环覆盖。 Rollback segment,一共有128个,分别从resg slot0 - resg slot127,每一个resg slot,也就是每一个回滚段,内部由1024个undo segment组成。 |
是,innodb_buffer_pool缓冲池中有undo页 |
尽量顺序写。 回滚,实际做的是与之前相反的工作,比如INSERT需要的是DELETE,而DELETE需要的是INSERT。 执行相反的UPDATE,将修改前的行放回去。 回滚操作写入磁盘时为随机写。 |
||
| redo log |
重做日志,在事务执行的过程中不断记录事务操作的变化。 恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。 用来保证事务的原子性和持久性。 |
InnoDB引擎层 | 物理日志,记录的是数据页的物理修改。 |
重做日志文件,ib_logfile0/ib_logfile1。 有自己的页结构,会循环覆盖。 |
是,专门的独立的redo缓冲区 |
尽量顺序写。 先写入日志缓冲中,然后按照一定的条件顺序写入redo日志文件。 恢复操作写入磁盘时为随机写。 |
||
| binlog |
二进制日志,在事务提交后进行记录。 用来备份, 通过主从复制来实现数据同步和读写分离。 |
MySQL数据库(上)层 | 逻辑日志,记录数据库所有增删改操作(sql语句)。 |
二进制日志文件,localhost-bin.000001~localhost-bin.00000n。 有自己的文件格式和文件结构,不会循环覆盖,追加写,文件写满再新建。 |
是,每个会话有一个默认32K的缓冲。 | 顺序写。 | ||
二、undo log与redo log的总结和补充
Undo 记录某数据被修改前的值,可以用来在事务失败时进行rollback;重要的是,undo log会产生redo log,也就是undo log的产生也会伴随redo log的产生,这是因为undo log也需要持久性的保护。即undo也是数据页的一部分。
Redo 记录某数据块被修改后的值,可以用来恢复未写入data file 的已成功事务更新的数据。即redo log是对数据页修改后刷脏的一个有力补充。即WAL技术,Write-Ahead Logging,先写日志文件,再写到数据库页缓存,最后刷到磁盘的数据库中。
例如某一事务的事务序号为T1,其对数据X进行修改,设X的原值是5,修改后的值为15,那么Undo日志为<T1, X, 5>,Redo日志为<T1, X, 15>。
三、redo log和binlog,以及2PC
redo log是在事务进行中不断被写入,所以每个事务对应多个日志条目。
binlog 是在事务提交完成后,进行一次写入。所以对于每个事务仅仅对应一个日志记录。
redo log日志刷盘机制和参数innodb_flush_log_at_trx_commit有关。
binlog 什么时候刷新到磁盘跟参数sync_binlog有关。
innodb_flush_log_at_trx_commit
0: 每隔1s,由系统后台线程刷log buffer,也就是把redo日志刷盘,这里会调用fsync,所以可能丢失最后1s的事务。
1: 每次commit时,刷redo日志,确定fsync刷盘。为默认值。
2: 每次提交时,刷redo日志到文件系统,不调用fsync刷盘,5.6.6之前是每隔1s刷盘,之后的版本是通过参数innodb_flush_log_at_timeout设置,默认也是1s。所以也可能丢最后一秒的事务。如果有掉电保护组件的话,可以开启。

sync_binlog
表示每多少个sync事件触发一次真正的binlog fsync刷盘,默认是1,表示每次commit时binlog都会fsync。
建议这两个参数都设置成1.
内部XA事务与2PC
InnoDB存储引擎提供了对XA事务的支持,并通过XA事务来支持分布式事务的实现。
分布式事务(Distributed Transactions)指的是允许多个独立的事务资源(transactional resources)参与到一个全局的事务中。全局事务也必须遵循ACID原则。
XA事务允许不同数据库之间的分布式事务,例如一台MySQL数据,一台Oracle数据库,只要全局事务中的每个节点都支持XA事务即可。此时,InnoDB的隔离级别必须是SERIALIZABLE。
分布式事务采用两阶段提交(two-phase commit)的方式。
在第一阶段,所有参与全局事务的节点开始准备(PREPARE),告诉事务管理器它们准备好提交了。
在第二阶段,事务管理器告诉资源管理器执行ROLLBACK还是COMMIT。如果任何一个节点显示不能提交,则所有节点被告知需要回滚。
所以,与本地事务对比,分布式事务多了一次PREPARE操作,待收到所有节点的同意信息后,再进行提交或者回滚操作。
以上讨论的是外部事务,即资源管理器是MySQL数据库本身。而在MySQL数据库内部也可以存在这样类似的分布式事务。
资源管理器可以是存储引擎或插件,所以可以是存储引擎和插件之间,或者存储引擎与存储引擎之间,这种被称为内部XA事务。
最为常见的内部XA事务存在于binlog与InnoDB存储引擎之间。
既然是XA事务,必然涉及到两阶段提交,对于内部XA而言,同样存在着提交的两个阶段。
这个两阶段提交是在开启binlog之后,redo与binlog的两阶段提交。
在更新一条数据时,会先执行,然后写入redo log中,redo log进入prepare状态,执行器执行完成。
然后执行器生成这个操作的binlog,并写入磁盘。
然后提交commit,更新完成。
假设在任何情况下(机器掉电)mysqld crash或者os crash,MySQL仍然能保证数据库的一致性。数据的一致性是如何做到的哪?正是二阶段提交。
我们结合几种场景来分析下二阶段提交是如何做到的:
1.prepare阶段,redo log落盘前,mysqld crash
2.prepare阶段,redo log落盘后,binlog落盘前,mysqld crash
3.commit阶段,binlog落盘后,mysqld crash
对于第一种情况,由于redo没有落盘,毫无疑问,事务的更新肯定没有写入磁盘,数据库的一致性不受影响;
对于第二种情况,这时候redo log写入完成,但binlog还未写入,是提交还是回滚呢?
对于第三种情况,此时,redo log和binlog都已经落盘,只是undo状态没有更新,虽然redo log和binlog已经一致了,事务是否应该提交?
对于第三种情况,我们可以搜集到未提交事务的binlog event,所以需要提交;
对于第二种情况,由于binlog未写入,需要通过执行回滚操作来保证数据库的一致性。
简而言之,对于异常的XA事务,若binlog已落盘,则事务应该提交;binlog未落盘,则事务就应该回滚。
注:以上XA事务的2PC流程主要参考第二篇,和书上稍微有些差别,书上写的是先提交binlog,我觉得可能更合理。但是不影响对事务2PC的整体理解。
参考资料:
《MySQL技术内幕InnoDB存储引擎》
MySQL的undo/redo日志和binlog日志,以及2PC的更多相关文章
- MySQL Binlog--事务日志和BINLOG落盘参数对磁盘IO的影响
参数说明 innodb_flush_log_at_trx_commit和sync_binlog 两个参数是控制MySQL 磁盘写入策略以及数据安全性的关键参数,不同参数设置对磁盘IO影响不同. 参数i ...
- MySQL 5.6 新参数对binlog日志量的优化
数据库版本:5.6.* 1.row日志image类型 参数binlog_row_image 控制着这种image类型,默认为FULL(log all columns),即记录before&af ...
- mysql主从复制问题之主从两端binlog日志不同步解决方案
主操作: 进入主的数据库查看状态: mysql> show master statusG; *************************** 1. row **************** ...
- mysql做了主从,删除binlog日志
在主服务器操作: 1.查看当前主从库是用哪个binlog日志在做组从 show master status show slave status 2.查看主库的binlog日志 show master ...
- mysql开启登录日志和sql日志 排查错误
首先看是否开启了日志 show global variables like '%general%'; set global general_log = on; // 打开 set global gen ...
- Logback分别打印info日志和error日志
<?xml version="1.0" encoding="utf-8" ?><configuration> <appender ...
- [PHP] PHP-FPM的access日志error日志和slow日志
PHP-FPM的错误日志建议打开,这样可以看到PHP的错误信息:一般是这个配置路径 /etc/php/7.3/fpm/pool.d/www.conf,日志目录如果需要自己建立PHP目录,一定要把权限赋 ...
- 【MySQL】undo,redo,2PC,恢复思维导图
http://blog.itpub.net/22664653/viewspace-2131353/
- 一生挚友redo log、binlog《死磕MySQL系列 二》
系列文章 原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 一生挚友redo log.binlog<死磕MySQL系列 二> 前言 咔咔闲谈 上期根据 ...
随机推荐
- 小烈送菜——奇怪的dp
小烈送菜 题目描述 小烈一下碰碰车就被乐满地的工作人员抓住了.作为扰乱秩序的惩罚,小烈必须去乐满地里的"漓江村"饭店端盘子. 服务员的工作很繁忙.他们要上菜,同时要使顾客们尽量高兴 ...
- 文件读取一些payload
Windows: C:boot.ini //查看系统版本 C:WindowsSystem32inetsrvMetaBase.xml //IIS配置文件 C:Windowsrepairsam //存储系 ...
- windows下的包管理器scoop
scoop(传送门) 安装 scoop是一个类似于linux下apt之类包管理器 安装scoop(Powershell 3+ and .NET Framework 4.5+) iex (new-ob ...
- java 面向对象(一):类与对象
1.面向对象学习的三条主线: * 1.Java类及类的成员:属性.方法.构造器:代码块.内部类 * * 2.面向对象的大特征:封装性.继承性.多态性.(抽象性) * * 3.其它关键字:this.su ...
- 数据可视化之powerBI基础(一) 如何查看PowerBI图表背后的数据
https://zhuanlan.zhihu.com/p/64405494 图表很直观,但有时候我们不仅想看图,也想更进一步查看生成该图表的明细数据,在PowerBI中有三种方式. (一)在图表上单击 ...
- hihoCoder 1049 后序遍历 最详细的解题报告
题目来源:后序遍历 解题思路:开始时我只知道先通过先序.中序求出二叉树,然后再后序遍历二叉树,这当然也是一种解题思路,但是会做一些无用功,比如:计算二叉树.其实,可以直接通过先序序列和中序序列直接求出 ...
- Apache Hudi重磅特性解读之存量表高效迁移机制
1. 摘要 随着Apache Hudi变得越来越流行,一个挑战就是用户如何将存量的历史表迁移到Apache Hudi,Apache Hudi维护了记录级别的元数据以便提供upserts和增量拉取的核心 ...
- 开会时CPU 飙升100%同事们都手忙脚乱记一次应急处理过程
告警 正在开会,突然钉钉告警声响个不停,同时市场人员反馈客户在投诉系统登不进了,报504错误.查看钉钉上的告警信息,几台业务服务器节点全部报CPU超过告警阈值,达100%. 赶紧从会上下来,SSH登录 ...
- Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解
随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...
- Go的100天之旅-04基础数据类型
基础数据类型 在变量的定义中,我们讲了每个变量是有类型的,类型在计算机中是用来约束数据的解释.Go语言和其它计算机语言一样,提供丰富了丰富的数据类型,我们就来看看到底有哪些类型,同时也可以比较一下它和 ...