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,才是将数据持久化到磁盘的操作
write
和fsync
的时机,可以由参数sync_binlog
控制,默认是0
。
值为0:表示每次提交事务都只
write
,由系统自行判断什么时候执行fsync
。虽然性能得到提升,但是机器宕机,page cache
里面的 binlog 会丢失。值为0:表示每次提交事务都会执行
fsync
,就如同 redo log 日志刷盘流程 一样。设置为N:N大于1,表示每次提交事务都
write
,但累积N
个事务后才fsync
。
4、两阶段提交
将redo log
的写入拆成了两个步骤prepare
和commit
,这就是两阶段提交,然后配合binlog
就可以实现MySQL崩溃时的数据恢复
明确一个前提:写入binlog
和redo 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、中继日志
中继日志只在主从服务器架构的从服务器上存在。从服务器为了与主服务器保持一致,要从主服务器读取二进制日志的内容,并且把读取到的信息写入 本地的日志文件 中,这个从服务器本地的日志文件就叫中继日志 。然后,从服务器读取中继日志,并根据中继日志的内容对从服务器的数据进行更新,完成主从服务器的 数据同步 。