# Mysql中的日志系统
Mysql中支持的日志有redo log、undo log、binlog(二进制日志文件)、error log、relay log;其日志系统相关的系统架构如下:
:-: ![](https://img.kancloud.cn/b1/71/b171003fed581607b318ec74a427cff6_815x618.png)
说明:redo log和undo log是归属与innodb的,并不是所有存储引擎都有。查询缓存在mysql8之后就没有了。innodb存储引擎在5.5版本时候是`插件`的形式运行的,在5.5之后就成为了默认的存储引擎。
## redo log
redo操作用于将数据重新恢复到新值,用于已经提交的事务当中。对于一个事务来说,执行commit语句之后并不能够保证修改的数据真正的持久化到磁盘中,只能保证对应的redo log日志持久化到磁盘当中(因此redo log的落盘会在commit之前执行)。数据持久化真正持久化到磁盘是操作系统内核的行为。如果在数据还没有真正的持久化到磁盘的时候系统挂了,内核中的脏页数据将会丢失,这个时候就可以使用redo log来进行恢复了。
redo属于存储引擎(InnoDB)层管理的机制,在Buffer Pool中会维护一块redo log pool的内存空间,当有DML语句执行的时候,会先将对应的日志内容写入到redo log pool中,最后在执行commit时,会在redo log中做上commit标识,同时落盘。也就是说当事务被commit之后数据并不是真正的落盘了,有可能还在Buffer pool中,只能保证redo log的内容落盘了。这种方式就称为WAL(write ahead log,预习日志)。而Buffer pool中的数据会在checkpoint中择时落盘。
:-: ![](https://img.kancloud.cn/1a/03/1a031f0defd2b59f325c3be14b22ce56_1346x721.png)
**Redo log的落盘机制**
在配置文件中的Mycat中可以配置`innodb_flush_log_at_trx_commit`属性来控制redo log的落盘机制,`innodb_flush_log_at_trx_commit`属性的取值如下:
* 1,默认值,事务提交时执行一次fsync操作,将日志落盘。
* 0,事务提交时直将内容写入redo log buffer中,由其他后台线程选择落盘的时机。
* 2,事务提交时将redo log的内容写入pagecache中,之后每隔1秒由fsync命令刷新落盘。
可见设置为0的时候mysql的线程的性能最高,但是丧失了事务的一致性。为1的话就可以实现强一致性。
:-: ![](https://img.kancloud.cn/f1/02/f10203d8a2a53e4726e322f3b88b3929_1001x779.png)
> 问:redo log是不是都是已经提交的事务?
当事务提交的时候会将redo log的内容写入redo log buffer中,这个时候并不是真正的写入redo log的日志文件中的。redo log buffer落盘的时机受后台线程的控制,由于redo log buffer是所有事务共享的且事务每次执行的命令的时候就会将命令写入redo log中;当事务A执行到了一半,而事务B提交了事务或者是后台线程刷新了redo log buffer中的脏页,因此就有可能导致事务A的redo log的内容也被落盘了,但是此时事务A并没有提交。
> 问:如何区分redo log中的事务是不是已经提交的事务?
对于一个修改x的命令,redo log的记录内容大致可以如下:<事务ID,修改行,旧值,新值>。
对于一个完整的事务T1,redo log的内容可能如下:
```
<T1 start>
...
<T1 commit>
```
当事务执行commit命令之前会在redo log中打上commit标志,如果事务T1在redo log file中没有最后的commit标志,是不用进行事务的恢复的。
> 问:checkpoint的作用是什么?
1. 在checkpoint之后开始或者提交的事务才需要进行恢复操作,可以缩短数据库进行重做日志时的恢复时间。
2. 当缓冲池不够用的时候,将脏页刷新到磁盘中。
记录的格式可能如下:
```
<checkpoint t1, t2,t3>
```
> 问:checkpoint什么时候起作用?
1. 数据库关闭时将所有的脏页落盘。
2. 主线程按照一定的时间刷新一定比例的脏页。
3. LRU可用页不多时。
4. 脏页的数量超过一定的比例时。
> 问:doublewrite是什么?
由于InnoDB每页的大小为16KB,而Linux文件系统支持的IO的最小单位是4K,磁盘IO的最小单位是512个字节,因此在脏页落盘的时候如果发现了断电而导致例如16KB只写了2KB,这个时候就会出现数据丢失的问题,使用redo是不能够恢复的。为了保证落盘这个过程的可靠性,InnoDB就引入了DoubleWrite机制,来解决部分写入的问题。
DoubleWrite由两部分组成,一个部分是内存中的DoubleWrite Buffer,大小为2MB;另外一部分是磁盘的共享表空间中连续的128个页,大小也是2MB。double的过程如下:
1. 当发生脏页落盘的时候,将脏页copy到doublewrite中。
2. 接着从double write buffer中写入顺序写入磁盘共享表空间中,每次1MB。
3. 做完之后将double write buffer中的数据写入各个表空间中,离散写入的。
在系统崩溃的时候在共享表空间中找到该页的最近一个副本,直接替换。
> 问:为什么redo log不需要doublewrite的支持?
>
> redo log每次写入的最小单位是512字节,也就是磁盘的最小单位。
## undo log
## binlog
binlog是Mysql server层维护的一种二进制文件,与redo log和undo log由存储引擎层维护不同。其主要作用有:
* 主从复制:MySQL Replication在Master端开启binlog,Master把它的二进制日志传递给slaves并回放来达到master-slave数据一致的目的。
* 数据恢复:通过mysqlbinlog工具恢复数据。
* 增量备份。
binlog文件的位置一般放在mysql安装目录下的data目录,可以使用如下命令来具体查看binlog的状态信息:
~~~
show variables like '%log_bin%';
~~~
:-: ![](https://img.kancloud.cn/59/60/59603cd6617eaa95f1098548e3eb200d_1182x262.png)
在mysql5.7中binlog默认是关闭的,可以修改配置文件my.cnf启动:
~~~
[mysqld]
log-bin=ON
~~~
查看binlog文件情况:
~~~
show binary logs;
show master status; # 查看当前写入的binlog文件
reset master; #清空binlog日志文件
~~~
:-: ![](https://img.kancloud.cn/d4/a9/d4a9fef8672039262e988c2ec5010800_986x692.png)
binlog文件是二进制文件,可以使用下面两种方式查看binlog文件的内容:
1. mysqlbinlog
~~~
mysqlbinlog binlog.000501
~~~
mysqlbinlog是官方提供的一个binlog的查看工具,windows系统在安装目录的bin目录下有。
2. 直接命令行解析
~~~
show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]
~~~
**binlog主从复制**
binlog主要用于主从复制中,在5.6版本之后有两种主从复制方式:binlog和GTID(全局事务标识符)。binlog用于主从复制的流程如下:
1. Master将数据改变记录到二进制日志(binary log)中。
2. Slave上的IO进程连接Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容。
3. Master接收到来自Slave的IO进程的请求后,负责复制的IO进程会根据请求信息读取日志指定位置之后的日志信息,返回给Slave的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置。
4. Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的 bin-log的件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master从某个bin-log的哪个位置开始往后的日志内容。
5. Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。
### 事务的两阶段提交
Mysql中有两种日志是用于备份数据的,redo log和binlog;binlog是mysql的server层所有的,redo log是InnoDB引擎所有的,而只有redo log能用于故障恢复。因此为了保证redo log和binlog中的逻辑一致性,redo log会先写入一个prepare标识,之后binlog写入,之后再提交事务,写入commit。
- 第一章 Java基础
- ThreadLocal
- Java异常体系
- Java集合框架
- List接口及其实现类
- Queue接口及其实现类
- Set接口及其实现类
- Map接口及其实现类
- JDK1.8新特性
- Lambda表达式
- 常用函数式接口
- stream流
- 面试
- 第二章 Java虚拟机
- 第一节、运行时数据区
- 第二节、垃圾回收
- 第三节、类加载机制
- 第四节、类文件与字节码指令
- 第五节、语法糖
- 第六节、运行期优化
- 面试常见问题
- 第三章 并发编程
- 第一节、Java中的线程
- 第二节、Java中的锁
- 第三节、线程池
- 第四节、并发工具类
- AQS
- 第四章 网络编程
- WebSocket协议
- Netty
- Netty入门
- Netty-自定义协议
- 面试题
- IO
- 网络IO模型
- 第五章 操作系统
- IO
- 文件系统的相关概念
- Java几种文件读写方式性能对比
- Socket
- 内存管理
- 进程、线程、协程
- IO模型的演化过程
- 第六章 计算机网络
- 第七章 消息队列
- RabbitMQ
- 第八章 开发框架
- Spring
- Spring事务
- Spring MVC
- Spring Boot
- Mybatis
- Mybatis-Plus
- Shiro
- 第九章 数据库
- Mysql
- Mysql中的索引
- Mysql中的锁
- 面试常见问题
- Mysql中的日志
- InnoDB存储引擎
- 事务
- Redis
- redis的数据类型
- redis数据结构
- Redis主从复制
- 哨兵模式
- 面试题
- Spring Boot整合Lettuce+Redisson实现布隆过滤器
- 集群
- Redis网络IO模型
- 第十章 设计模式
- 设计模式-七大原则
- 设计模式-单例模式
- 设计模式-备忘录模式
- 设计模式-原型模式
- 设计模式-责任链模式
- 设计模式-过滤模式
- 设计模式-观察者模式
- 设计模式-工厂方法模式
- 设计模式-抽象工厂模式
- 设计模式-代理模式
- 第十一章 后端开发常用工具、库
- Docker
- Docker安装Mysql
- 第十二章 中间件
- ZooKeeper