MySQL 的日志种类
11月 5, 2021
MySQL 数据库存在还多类型的日志,每一种日志都代表了一种数据库活动,了解这些日志可以侧面了解数据库的运行过程,在日常开发中也可以适当的运用。MySQL 中常见的日志文件有:错误日志、二进制日志、慢查询日志、一般查询日志、重做日志、回滚日志、中继日志,下面开始详细介绍一下。
错误日志(error log) #
错误日志对 MySQL 的启动、运行、关闭进行了记录。该文件不仅记录了所有的错误信息,也记录了一些警告信息,可以通过下面命令查看。
show variables like 'log_error'\G;
二进制日志(binlog) #
二进制日志记录了对 MySQL 数据库执行更改的所有操作,但是不包括 select
和 show
这类操作,因为这类操作对数据本身没有修改。
binlog 分为三种格式:STATEMENT
、ROW
和 MIXED
。在 MySQL 5.7.7 之前,默认的格式是 STATEMENT
, MySQL 5.7.7 之后,默认值是 ROW
。日志格式通过 binlog_format
配置参数指定。
- STATMENT:每一条会修改数据的 SQL 语句会记录到 binlog 中 。
- 优点:不需要记录每一行的变化,减少了 binlog 日志量,节约了 IO,从而提高了性能;
- 缺点:在某些情况下会导致主从数据不一致,比如执行 sysdate() 、slepp() 等 。
- ROW:不记录 SQL 的上下文信息,仅需记录哪条数据被修改。记两条,更新前和更新后都有。
- 优点:不会出现某些特定情况下的存储过程、或 function、或 trigger 的调用和触发无法被正确复制的问题 ;
- 缺点:会产生大量的日志,尤其是
alter table
的时候会让日志暴涨。
- MIXED:前两种模式的混合,一般的复制使用 STATEMENT 模式保存 binlog ,对于 STATEMENT 模式无法复制的操作使用 ROW 模式保存 binlog。
binlog 一般有以下作用:
- 数据恢复
- 主从数据同步
- 审计分析
慢查询日志(slow query log) #
在MySQL启动时可以通过long_query_time
参数设置一个阀值,将运行时间超过该值的所有 SQL 语句都记录到慢查询日志中,DBA 可以定期来检查,确认是否有 SQL 语句需要优化,阀值默认为 10 秒。
通过下面命令查看慢查询日志:
mysql> show variables like 'slow_query_log';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)
/* 设置慢查询时间 */
mysql> set global long_query_time=0.1;
Query OK, 0 rows affected (0.00 sec)
MySQL 从 5.1 开始将慢查询的日志记录到一张表slow_log
中,这样用户查询起来会更加方便。
查询日志(general log) #
查询日志记录了所有到达数据库的请求信息,并保存在表generl_log
中。因为数据了非常大,一般不会打开,只用于排查问题的等用途。
重做日志(redo log) #
重做日志(redo log)非常重要,InnoDB 通过重做日志实现了事务的持久性。redo log 会把事务在执行过程中的所有修改都记录下来(即使没有提交),首先会写到 log buffer 的缓冲区里,log buffer 的大小是有限的,当大小到达一定量时会通过一定频率顺序地写入到磁盘。redo log 占用的磁盘空间在它对应的脏页已经被刷新到磁盘后即可被覆盖。
MySQL 通过 redo、undo 日志实现 WAL(Write Ahead Log)预写日志机制,即事务在提交之前会确保 redo log 已经写到了磁盘里,这样就算数据库宕机,都可以在恢复时从 redo log 恢复数据。
与 Binlog 的区别:
- redo log 是 InnoDB 引擎特有的,binlog 是 MySQL 实现的,所有的引擎都可以用。
- redo log 记录的是每个页更改的物理记录,binlog 是一个事物具体操作的逻辑日志。
- redo log 是循环写的,空间固定,binlog 是可以追加写入的,即写到一定大小会换下个文件继续写。
由于 redo log 和 binlog 是两个独立的逻辑,为了保证数据的一致性,数据库事务采用两阶段提交,理论上先写 redo log 后写 binlog,当两者都写入磁盘后,事务才算完成。
回滚日志(undo log) #
MySQL 通过回滚日志(undo log)实现了数据库的原子性,同时也为 MVCC 提供了多版本并发控制下的非锁定读。事务的每一条数据的修改都对应了一条 undo log,回滚日志除了能够在发生错误或者用户执行 ROLLBACK
时提供回滚相关的信息,它还能够在整个系统发生崩溃、数据库进程直接被杀死后,当用户再次启动数据库进程时,还能够立刻通过查询回滚日志将之前未完成的事务进行回滚,所以事务在提交前会确保 undo log 写到了磁盘上。
回滚日志是逻辑格式的日志,在执行 undo 的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,这一点是不同于 redo log 的。
redo 和 undo 的关系大致如下:
假设有A、B两个数据,值分别为1,2.
1. 事务开始
2. 记录 A=1 到 undo log
3. 修改 A=3
4. 记录 A=3 到 redo log
5. 记录 B=2 到 undo log
6. 修改 B=4
7. 记录 B=4 到 redo log
8. 将 redo log 写入磁盘
9. 事务提交
中继日志(relay log) #
在实现数据库主从复制的时候,需要用到中继日志。从库的 I/O 线程从主库复制 binlog 到自己的中继日志中,由从库的主线程进行读取并执行,这样主库就不需要等待从库执行完再执行自己的下一步操作了。
总结 #
最重要的就是重做日志、回滚日志和 binlog,重点关注。