MySQL 中的日志类型有很多,每种日志都有不同的功能,一般有以下几种日志:
| 日志类型 | 写入日志的信息 |
|---|---|
| 错误日志 | 记录在启动,运行或停止mysqld时遇到的问题 |
| 通用查询日志 | 记录建立的客户端连接和执行的语句 |
| 二进制日志 | 记录更改数据的语句 |
| 中继日志 | 从复制主服务器接收的数据更改 |
| 慢查询日志 | 记录所有执行时间超过 long_query_time 秒的所有查询或不使用索引的查询 |
| DDL日志(元数据日志) | 元数据操作由DDL语句执行 |
概述
在 MySQL 中有三种日志,他们分别是:
- binlog
- redo log
- undo log
binlog 以事件形式记录数据库表结构和表数据变更的二进制日志,比如 insert、update、delete、create、truncate 等等操作,不会记录 select、show 操作,因为没有对数据产生影响。binlog的主要目的是复制和恢复。
redolog 同样是记录数据的变更,但是 redolog 与 binlog 记录的日志形式和作用存在差别,这个后面会深入去探究。
undo log 和前面两种日志不同,undo log 的作用主要用于回滚,MySQL数据库的事务的原子性就是通过 undo log 实现的。undo log主要存储的是数据的逻辑变化日志,比如说我们要insert一条数据,那么undo log就会生成一条对应的delete日志。简单点说,undo log记录的是数据修改之前的数据,因为需要支持回滚。
binLog
MySQL 的二进制日志 binlog 可以说是 MySQL 最重要的日志,它记录了所有的 DDL 和 DML 语句(除了数据查询语句select、show等),以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日志是事务安全型的。binlog 的主要目的是复制和恢复。
binlog 日志的两个最重要的使用场景
- MySQL 主从复制:MySQL Replication在Master端开启binlog,Master把它的二进制日志传递给slaves来达到master-slave数据一致的目的
- 数据恢复:通过使用 MySQLbinlog 工具来恢复数据
这里的数据恢复是指,明确了要恢复哪个时间段的数据,是需要操作的,而不是自动的。因为 binlog 和 redo log 不同,它全量记录数据的更改,而没有办法知道哪部分记录丢失了,redo log 则会将持久化的数据给抹除,所以可以自动将没有持久化的数据给持久化到磁盘。
为什么 redo log 具有 crash-safe 的能力,而 binlog 没有?
redo log 是什么?
一个固定大小,“循环写”的日志文件,记录的是物理日志——“在某个数据页上做了某个修改”。
binlog 是什么?
一个无限大小,“追加写”的日志文件,记录的是逻辑日志——“给 ID=2 这一行的 c 字段加1”。
redo log 和 binlog 有一个很大的区别就是,一个是循环写,一个是追加写。也就是说 redo log 只会记录未刷盘的日志,已经刷入磁盘的数据都会从 redo log 这个有限大小的日志文件里删除。binlog 是追加日志,保存的是全量的日志。
当数据库 crash 后,想要恢复未刷盘但已经写入 redo log 和 binlog 的数据到内存时,binlog 是无法恢复的。虽然 binlog 拥有全量的日志,但没有一个标志让 innoDB 判断哪些数据已经刷盘,哪些数据还没有。
举个栗子,binlog 记录了两条日志:
给 ID=2 这一行的 c 字段加1
给 ID=2 这一行的 c 字段加1
在记录1刷盘后,记录2未刷盘时,数据库 crash。重启后,只通过 binlog 数据库无法判断这两条记录哪条已经写入磁盘,哪条没有写入磁盘,不管是两条都恢复至内存,还是都不恢复,对 ID=2 这行数据来说,都不对。
但 redo log 不一样,只要刷入磁盘的数据,都会从 redo log 中抹掉,数据库重启后,直接把 redo log 中的数据都恢复至内存就可以了。这就是为什么 redo log 具有 crash-safe 的能力,而 binlog 不具备。
