MySQL四种日志binlog/redolog/relaylog/undolog
优质博文:IT-BLOG-CN
一、binlog
binlog记录数据库表结构和表数据变更,比如update/delete/insert/truncate/create,它不会记录select。存储着每条变更的SQL语句和XID事务Id等等。binlog日志文件如下:
[root@192.168.10.11]# mysqlbinlog mysql-binlog.0000012
..........
# at 523
# 168654 20:22:43 server id 1 end_log_pos 843 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=156521934/*!*/;
INSERT INTO student('name','age','sex') VALUES('ZZX',20,'1'); # 执行的SQL语句
/*!*/;
# at 669
#168654 20:22:45 server id 1 end_log_pos 876 Xid = 12 #执行的时间和事务ID
主要有两个作用:复制和恢复数据
【1】MySQL架构为了高可用性都是一主多从,从服务器需要与主服务器保持数据一致,这就是通过binlog进行复制;
【2】数据库的数据如果被误删,可以通过binlog数据进行恢复。
因为
binlog记录了数据库表的逻辑变更,所以可以用binlog进行主从复制和恢复数据。
二、redo log
MySQL执行SQL修改语句时,肯定是先把这条记录查出来,然后再将这条进行进行修改。因为Mysql的基本存储结构是页,记录都存在页里边,所以MySQL是先把这条记录所在的页找到,然后把该页加载到内存中,将对应记录进行修改。现在就可能存在一个问题:如果在内存中把数据改了,还没来得及落磁盘,而此时的数据库挂了,导致这次修改丢失了怎么办?

如果每个请求都需要将数据立马同步到磁盘,那速度会很慢,MySQL可能也顶不住。所以MySQL引入了redo log,内存写完了,然后会写一份redo log,这份redo log记载着这次在某个页上做了什么修改。
写redo log的时候,也会有buffer,是先写buffer,再真正落到磁盘中的。至于从buffer什么时候落磁盘,会有配置供我们配置。

写redo log也是需要写磁盘的,但它的好处就是顺序IO(我们都知道顺序IO比随机IO快非常多)。
所以,redo log的存在为了:当我们修改的时候,写完内存了,但数据还没真正写到磁盘的时候。此时我们的数据库挂了,我们可以根据redo log来对数据进行恢复。因为redo log是顺序IO,所以写入的速度很快,并且redo log记载的是物理变化(x页做了y修改),文件的体积很小,恢复速度很快。
三、binlog与redolog的区别
两个日志较为相似,这里总结下两者的主要区别:
【1】存储内容不同: binlog记载的是update/delete/insert这样的SQL语句,而redo log记载的是物理修改的内容(x页修改了y)。redo log记录的是数据的物理变化,binlog记录的是数据的逻辑变化。
【2】功能: redo log的作用是为持久化而生的。写完内存,如果数据库挂了,那我们可以通过redo log来恢复内存还没来得及刷到磁盘的数据,将redo log加载到内存里边,那内存就能恢复到挂掉之前的数据了。
binlog的作用是复制和恢复而生的。主从服务器需要保持数据的一致性,通过binlog来同步数据。如果整个数据库的数据都被删除了,binlog存储着所有的数据变更情况,那么可以通过binlog来对数据进行恢复。
如果整个数据库的数据都被删除了,那我可以用redo log的记录来恢复吗?
不能,因为功能的不同,redo log 存储的是物理数据的变更,如果我们内存的数据已经刷到了磁盘了,那redo log的数据就无效了。所以redo log不会存储着历史所有数据的变更,文件的内容会被覆盖的。
【3】写入细节不同: redo log是MySQL的InnoDB引擎所产生的。binlog无论MySQL任何引擎都会有的。
InnoDB是有事务的,事务的四大特性之一:持久性就是靠redo log来实现的(如果写入内存成功,但数据还没真正刷到磁盘,如果此时的数据库挂了,我们可以靠redo log来恢复内存的数据,这就实现了持久性)。
上面也提到,在修改的数据的时候,binlog会记载着变更的类容,redo log也会记载着变更的内容。(只不过一个存储的是物理变化,一个存储的是逻辑变化)。那他们的写入顺序是什么样的呢?
redo log事务开始的时候,就开始记录每次的变更信息,而binlog是在事务提交的时候才记录。
于是新有的问题又出现了:我写其中的某一个log,失败了,那会怎么办?现在我们的前提是先写redo log,再写binlog,我们来看看:
■ 如果写redo log失败了,那我们就认为这次事务有问题,回滚,不再写binlog。
■ 如果写redo log成功了,写binlog,写binlog写一半了,但失败了怎么办?我们还是会对这次的事务回滚,将无效的binlog给删除(因为binlog会影响从库的数据,所以需要做删除操作)
■ 如果写redo log和binlog都成功了,那这次算是事务才会真正成功。
简单来说:MySQL需要保证redo log和binlog的数据是一致的,如果不一致,那就乱套了。
■ 如果redo log写失败了,而binlog写成功了。那假设内存的数据还没来得及落磁盘,机器就挂掉了。那主从服务器的数据就不一致了。(从服务器通过binlog得到最新的数据,而主服务器由于redo log没有记载,没法恢复数据)
■ 如果redo log写成功了,而binlog写失败了。那从服务器就拿不到最新的数据了。
MySQL通过两阶段提交来保证redo log和binlog的数据是一致的。

阶段1:InnoDB redo log写盘,InnoDB事务进入prepare状态
阶段2:binlog写盘,InooDB事务进入commit状态
每个事务binlog的末尾,会记录一个XID event,标志着事务是否提交成功,也就是说,恢复过程中,binlog最后一个XID event之后的内容都应该被purge。
如果binlog没有正常关闭,mysql server可能crash过,我们需要调用MYSQL_BIN_LOG::recover:找到最后一个XID完成最后一次事务的两阶段提交InnoDB commit。因此,需要遍历binlog文件,找到最后一个合法event集合,并purge无效binlog
四、relay-log
从服务器I/O线程将主服务器的二进制日志读取过来记录到从服务器本地文件,然后从服务器SQL线程会读取relay-log日志的内容并应用到从服务器,从而使从服务器和主服务器的数据保持一致

show variables like '%relay%';
#结果
+---------------------------+----------------------------------+
| Variable_name | Value |
+---------------------------+----------------------------------+
| max_relay_log_size | 0 |
| relay_log | relay-mysql |
| relay_log_basename | /var/lib/mysql/relay-mysql |
| relay_log_index | /var/lib/mysql/relay-mysql.index |
| relay_log_info_file | relay-log.info |
| relay_log_info_repository | FILE |
| relay_log_purge | ON |
| relay_log_recovery | ON |
| relay_log_space_limit | 0 |
| sync_relay_log | 10000 |
| sync_relay_log_info | 10000 |
+---------------------------+----------------------------------+
max_relay_log_size:relay log允许的最大值,如果该值为0,则默认值为max_binlog_size (1G)。如果不为0,则max_relay_log_size则为最大的relay_log文件大小;
relay_log: 定义relay_log的位置和名称,如果值为空,则默认位置在数据文件的目录;
relay_log_index:定义relay_log索引的位置和名称,记录有几个relay_log文件,默认为2个
cat /var/lib/mysql/relay-mysql.index
#结果
./relay-mysql.000241
./relay-mysql.000242
relay_log_info_file:定义relay-log.info的位置和名称。relay-log.info记录master主库的binary_log的恢复位置和从库relay_log的位置;
[root@localhost ~]# cat /var/lib/mysql/relay-log.info
#结果
7
./relay-mysql.000242
19421766
mysql-bin.000094
34300252
0
0
1
relay_log_purge:是否自动清空中继日志,默认值为1(启用);
relay_log_recovery:
当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这样就保证了relay-log的完整性。默认情况下该功能是关闭的,将relay_log_recovery的值设置为1时,可在slave从库上开启该功能,建议开启;
sync_relay_log:当设置为1时,slave的I/O线程每次接收到master发送过来的binlog日志都要写入系统缓冲区,然后刷入relay log中继日志里,这样是最安全的,因为在崩溃的时候,你最多会丢失一个事务,但会造成磁盘的大量I/O。当设置为0时,并不是马上就刷入中继日志里,而是由操作系统决定何时来写入,虽然安全性降低了,但减少了大量的磁盘I/O操作。这个值默认是0,可动态修改;
sync_relay_log_info:这个参数和sync_relay_log参数一样。
五、undo log
undo log主要有两个作用:回滚和多版本控制MVCC
在数据修改的时候,不仅记录了redo log,还记录undo log,如果因为某些原因导致事务失败或回滚了,可以用undo log进行回滚
undo log主要存储的也是逻辑日志,比如我们要insert一条数据了,那undo log会记录的一条对应的delete日志。我们要update一条记录时,它会记录一条对应相反的update记录。
这也应该容易理解,毕竟回滚嘛,跟需要修改的操作相反就好,这样就能达到回滚的目的。因为支持回滚操作,所以我们就能保证:“一个事务包含多个操作,这些操作要么全部执行,要么全都不执行”。【原子性】
因为undo log存储着修改之前的数据,相当于一个前版本,MVCC实现的是读写不阻塞,读的时候只要返回前一个版本的数据就行了。
MySQL四种日志binlog/redolog/relaylog/undolog的更多相关文章
- Mysql 四种事务隔离介绍以及锁机制
还有很多不太懂,这里收集几份大佬文章“飞机票”,待我整理好了,再好好写一篇文章吧. MySQL的四种事务隔离级别 https://www.cnblogs.com/huanongying/p/70215 ...
- Mysql三种日志(binlog,redolog,undolog)的作用和区别
Mysql有三种很重要的日志也是面试经常涉及到的考点,分别是 binlog .redo log和undo log, 这里面binlog 是server层实现的日志,而redo log 和undo lo ...
- MySQL四种类型日志:Error Log、General Query Log、Binary Log、Slow Query Log
MySQL Server 有四种类型的日志——Error Log.General Query Log.Binary Log 和 Slow Query Log. 第一个是错误日志,记录mysqld的一些 ...
- Mysql 数据恢复流程 基于binlog redolog undolog
注:文中有个易混淆的地方 sql事务,即每次数据库操作生成的事务,这个事务trx_id只在undolog里存储,同时undolog维护了此事务是否完成的状态. 日志持久化事务,为了保证redolog和 ...
- 细说Mysql四种安装方法及自动化部署
一.简介 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库, 每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据. 我们也可以将数据存储在文件中,但是 ...
- mysql 几种日志
mysql 5.5 有以下几种日志: 错误日志(error log): log-err 查询日志(general query log): log 慢查询日志: -log-slow-queries ...
- 【转载】mysql 四种隔离级别分析
sql标准中,有四种隔离级别,各个离级别都有各自的规则,隔离级别越低,允许并发越大,消耗的资源越少,但是越不安全,下面就mysql数据库来分别介绍一下(每个存储引擎实施的隔离级别会有稍微的不同)mys ...
- MySQL 四种隔离级别
什么是事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做. 事务的结束有 ...
- MySql四种隔离级别
什么是事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做. 事务的结束有 ...
- c#之mysql四种带事务批量插入
前言 对于像我这样的业务程序员开发一些表单内容是家常便饭的事情,说道表单 我们都避免不了多行内容的提交,多行内容保存,自然要用到数据库,如果循环打扰我数据库,数据库也会觉得很累,从而增加数据库服务器压 ...
随机推荐
- CentOS 8.x 编译安装LNMP(Linux + Nginx + MySQL + PHP)架构部署动态网站环境
LNMP动态网站部署架构是一套由Linux + Nginx + MySQL + PHP组成的动态网站系统解决方案,具有免费.高效.扩展性强且资源消耗低等优良特性,目前正在被广泛使用. 前传: 1.Ce ...
- Android studio应用
菜单的使用 public class FirstActivity extends AppCompatActivity { @Override protected void onCreate(Bundl ...
- 高并发解决方案之 mysql悲观锁:select ... for update
select ... for update 场景:多个进程都先读后写咋办,需要的是让他们串行执行. 比如库存的减少.一般这些操作都是很长一串并且是开启事务的.如果库存刚开始读的时候是1,而立马另一个进 ...
- 对Java要学东西的认识 (一点点javascript见解)
JavaScript是一种脚本语言,它采用小程序段的方式实现编程.像其它脚本语言一样,JavaScript同样已是一种解释性语言,它提供了一个易的开发过程.它的基本结构形式与C.C++.VB十分类似. ...
- MongoDB:内嵌文档查询匹配 查询集合中的文档
1.db.getCollection('Notification').find({ Title:{$regex:/班/}, "Message.TargetUrl":{$regex: ...
- FileLocator Pro注册机
- mybatis-config.xml头信息
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 P ...
- c# + appium 连接设备自动化
//private static AndroidDriver<AppiumWebElement> _driver; //private static AppiumLocalService ...
- RabbitMQ问题汇总
内网通过代理服务器访问MQ服务器,无法连接 使用的是socket连接,要设置socket代理,而不是http代理 Properties prop = System.getProperties(); / ...
- 【vue】数据代理
Object.defineProperty()方法 我们先来看几段代码 常用添加属性的方法,以添加age举例 ,点击查看代码 let person = { name: '张三', sex: '男', ...