MySQL中的日志

一、重做日志(redo_log)

1、概述

redo log(重做日志)是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力。

比如 MySQL 实例挂了或宕机了,重启时,InnoDB存储引擎会使用redo log恢复数据,保证数据的持久性与完整性。

2、刷盘时机

InnoDB给出 innodb_flush_log_at_trx_commit 参数,支持三种策略

  • 设置值为0表示每次事务提交时不进行刷盘操作

  • 设置值为1表示每次事务提交时都将进行刷盘操作(默认值),提交时会调用 fsync 对 redo log 进行刷盘

  • 设置值为2表示每次事务提交时都只把 redo log buffer 内容写入 page cache由操作系统自己决定什么时候同步到磁盘文件

另外,InnoDB 存储引擎有一个后台线程,每隔1 秒,就会把 redo log buffer 中的内容写到文件系统缓存(page cache),然后调用 fsync 刷盘。如果redo log buffer 占用的空间即将达innodb_log_buffer_size 一半的时候,后台线程会主动刷盘。

3、日志文件组

硬盘上存储的 redo log 日志文件不只一个,而是以一个日志文件组的形式出现的,每个的redo日志文件大小都是一样的。

它采用的是环形数组形式,从头开始写,写到末尾又回到头循环写,如下图所示。

参数设置

  • innodb_log_group_home_dir :指定 redo log 文件组所在的路径,默认值为 ./ ,表示在数据库的数据目录下。MySQL的默认数据目录( var/lib/mysql )下默认有两个名为 ib_logfile0 ib_logfile1 的文件,log buffer中的日志默认情况下就是刷新到这两个磁盘文件中。此redo日志文件位置还可以修改。

  • innodb_log_files_in_group指明redo log file的个数,命名方式如:ib_logfile0,iblogfile1...iblogfilen。默认2个,最大100个。可通过show variables like 'innodb_log_files_in_group';查看并设置

  • innodb_flush_log_at_trx_commit:控制 redo log 刷新到磁盘的策略,默认为1。

  • innodb_log_file_size:单个 redo log 文件设置大小,默认值为 48M 。最大值为512G,注意最大值指的是整个 redo log 系列文件之和,即(innodb_log_files_in_group * innodb_log_file_size )不能大于最大值512G。可通过show variables like 'innodb_log_file_size';查看并设置

二、归档日志(bin_log)

1、概述

bin_log记录了数据库所有执行的DDL DML 等数据库更新事件的语句,但是不包含没有修改任何数据的语句(如数据查询语句select、show等)

不管用什么存储引擎,只要发生了表数据更新,都会产生 binlog 日志,属于逻辑日志

可以说MySQL数据库的数据备份、主备、主主、主从都离不开binlog,需要依靠binlog来同步数据,保证数据一致性,注意:二进制日志,MySQL5.7默认是关闭的,MySQL8.0默认是打开的

2、记录格式

binlog 日志有三种格式,可以通过binlog_format参数指定。

  • statement:记录的内容是SQL语句原文,但是有个问题,update_time=now()这里会获取当前系统时间,直接执行会导致与原库的数据不一致。

  • row:记录了修改的具体数据,但是这种格式,需要更大的容量来记录,比较占用空间,恢复与同步时会更消耗IO资源,影响执行速度。

  • mixed:混合上面两个格式

3、写入时机

binlog的写入时机也非常简单,事务执行过程中,先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中。

因为一个事务的binlog不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache

  • 上图的 write,是指把日志写入到文件系统的 page cache,并没有把数据持久化到磁盘,所以速度比较快

  • 上图的 fsync,才是将数据持久化到磁盘的操作

writefsync的时机,可以由参数sync_binlog控制,默认是0

  • 值为0:表示每次提交事务都只write,由系统自行判断什么时候执行fsync。虽然性能得到提升,但是机器宕机,page cache里面的 binlog 会丢失。

  • 值为0:示每次提交事务都会执行fsync,就如同 redo log 日志刷盘流程 一样。

  • 设置为N:N大于1,表示每次提交事务都write,但累积N个事务后才fsync

4、两阶段提交

redo log的写入拆成了两个步骤preparecommit,这就是两阶段提交,然后配合binlog就可以实现MySQL崩溃时的数据恢复

明确一个前提:写入binlogredo log的commit两个阶段为提交事务的具体落地方式

  • 如果在没写入redo log prepare阶段,MySQL崩溃了,此时redo log日志没有该次事务的日志信息,也没有binlog,也就是说事务没提交,此时MySQL会回滚该事务

  • 如果在写入redo log prepare之后事务提交之前,MySQL崩溃了,此时redo log日志中只有prepare阶段的日志,没有binlog,也就是说事务没提交,此时MySQL会回滚该事务

  • 如果在写入binlog之后,MySQL崩溃了,此时redo log日志中只有prepare阶段的日志,有binlog,也就是说事务已经提交,此时MySQL会提交该事务

三、回滚日志(undo_log

  • 用于数据的恢复,我们自己的数据恢复和MVCC的数据恢复

  • 用于ROLLBACK回滚依据

四、其他日志

1、慢查询日志

Mysql之慢了怎么办? - 知识星光 (peakliu.top)

2、通用查询日志

通用查询日志用来 记录用户的所有操作 ,包括启动和关闭MySQL服务、所有用户的连接开始时间和截止时间、发给 MySQL 数据库服务器的所有 SQL 指令等。当我们的数据发生异常时,查看通用查询日志,还原操作时的具体场景,可以帮助我们准确定位问题。

3、错误日志

在MySQL数据库中,错误日志功能是 默认开启 的。而且,错误日志 无法被禁止

默认情况下,错误日志存储在MySQL数据库的数据文件夹下,名称默认为 mysqld.log (Linux系统)hostname.err (mac系统)。

4、中继日志

中继日志只在主从服务器架构的从服务器上存在。从服务器为了与主服务器保持一致,要从主服务器读取二进制日志的内容,并且把读取到的信息写入 本地的日志文件 中,这个从服务器本地的日志文件就叫中继日志 。然后,从服务器读取中继日志,并根据中继日志的内容对从服务器的数据进行更新,完成主从服务器的 数据同步