MySQL 的日志种类

MySQL 的日志种类

Nov 5, 2021
数据库, MySQL

MySQL 数据库存在还多类型的日志,每一种日志都代表了一种数据库活动,了解这些日志可以侧面了解数据库的运行过程,在日常开发中也可以适当的运用。MySQL 中常见的日志文件有:错误日志、二进制日志、慢查询日志、一般查询日志、重做日志、回滚日志、中继日志,下面开始详细介绍一下。

错误日志(error log) #

错误日志对 MySQL 的启动、运行、关闭进行了记录。该文件不仅记录了所有的错误信息,也记录了一些警告信息,可以通过下面命令查看。

show variables like 'log_error'\G;

二进制日志(binlog) #

二进制日志记录了对 MySQL 数据库执行更改的所有操作,但是不包括 selectshow 这类操作,因为这类操作对数据本身没有修改。

binlog 分为三种格式:STATEMENTROWMIXED。在 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 一般有以下作用:

  1. 数据恢复
  2. 主从数据同步
  3. 审计分析

慢查询日志(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,重点关注。

本文以 CC 署名-非商业性使用-禁止演绎 4.0 国际 协议进行许可。

上一篇:数据库的索引

下一篇:InnoDB 的缓冲页管理