0%

MySQL的日志系统

归档日志binlog

归档日志记录了所有对MySQL数据库执行更改的所有操作(不包括SELECT和SHOW这样不会修改数据的操作)

作用

  1. 恢复:用户可以通过binlog对数据库中的数据进行恢复。
  2. 复制:可以通过binlog使得两台MySQL数据库之间进行实时同步。
  3. 审计:通过binlog来判断是否存在对数据库进行注入的攻击。

日志格式

binlog_format参数记录了binlog的格式,可选值由ROW,STATEMENT和MIXED。

ROW格式下记录了表的更改情况。

STATEMENT格式记录了日志的逻辑SQL语句。

MIXED格式下,MySQL会默认采用STATEMENT格式进行binlog的记录,但是在一些特殊的情况下会使用ROW格式(例如使用了UUID和RAND函数)。

错误日志

错误日志文件对MySqlQL的启动、关闭、运行过程进行记录,记录所有的错误日志以及一部分的警告或正确的信息。可以使用如下命令来定位错误日志文件。

1
2
3
4
5
6
7
mysql> SHOW VARIABLES LIKE 'log_error';
+---------------+--------------------------+
| Variable_name | Value |
+---------------+--------------------------+
| log_error | /var/log/mysql/error.log |
+---------------+--------------------------+
1 row in set (0.00 sec)

慢查询日志

慢查询日志可以帮助定位可能存在问题的SQL语句,从而帮助SQL语句优化。在MySQL运行期间,运行时间超过参数long_query_time的值(默认为10)的所有SQL语句都记录到慢查询日志之中。

查询日志

查询日志记录了所有对MySQL数据库请求的信息,无论这些请求是否得到了正确的执行。

重做日志redo log

当InnoDB引擎在进行更新的时候,会先把记录写到redo log中,同时更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录保存到磁盘里面。有了redo log,InnoDB保证了可以在数据库发生异常重启时之前提交的记录不会丢失。

binlog与redo log区别

  • redo log是InnoDB独有的日志系统,而Binlog对于所有的引擎都可以使用。
  • 只依靠Binlog无法实现Crash-safe能力因此InooDB引擎才引入了redo log来实现Crash-safe。
  • redo log是循环写的,空间固定会用完;binlog 是可以追加写入的,在写到一定大小后会切换到下一个,不会覆盖以前的日志。
  • redo log是物理日志,记录的是在某个数据页上做了什么修改;binlog 是逻辑日志,记录的是这个语句的原始逻辑。

二阶段提交

为了保证两份日志之间的逻辑一致,必须要有二阶段提交的操作。在二阶段提交的过程中,需要先写入redo log,然后进入prepare阶段,之后写入binlog,提交事务,处于commit状态,完成二阶段提交。

如果不使用二阶段提交的方案,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致。

如果选择先写redo log后写binlog。假设在redo log写完,binlog 还没有写完的时候,MySQL出现崩溃的情况。redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,但是由于 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。然后你会发现,如果需要用这个 binlog 来恢复临时库的话,由于这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 c 的值就是 0,与原库的值不同。

如果先写binlog后写redo log。如果在binlog写完之后 crash,由于redo log还没写,崩溃恢复以后这个事务无效,所以这一行 c 的值是 0。但是 binlog 里面已经记录了“把 c 从 0 改成 1”这个日志。所以,在之后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 c 的值就是 1,与原库的值不同。