日志是 mysql
数据库的重要组成部分,记录着数据库运行期间各种状态信息。mysql
日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。
1. binlog
binlog
用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。binlog
是 mysql
的逻辑日志,并且由 Server
层进行记录,使用任何存储引擎的 mysql
数据库都会记录 binlog
日志。
-
逻辑日志:可以简单理解为记录的就是sql语句 。
-
物理日志:
mysql
数据最终是保存在数据页中的,物理日志记录的就是数据页变更 。
binlog
是通过追加的方式进行写入的,可以通过max_binlog_size
参数设置每个 binlog
文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志
binlog使用场景
在实际应用中, binlog
的主要使用场景有两个,分别是 主从复制 和 数据恢复 。
-
主从复制 :在
Master
端开启binlog
,然后将binlog
发送到各个Slave
端,Slave
端重放binlog
从而达到主从数据一致。 -
数据恢复 :通过使用
mysqlbinlog
工具来恢复数据。
binlog刷盘时机
对于 InnoDB
存储引擎而言,只有在事务提交时才会记录biglog
,此时记录还在内存中,那么 biglog
是什么时候刷到磁盘中的呢?
mysql
通过 sync_binlog
参数控制 biglog
的刷盘时机,取值范围是 0-N
:
-
0:不去强制要求,由系统自行判断何时写入磁盘;
-
1:每次
commit
的时候都要将binlog
写入磁盘; -
N:每N个事务,才会将
binlog
写入磁盘。
从上面可以看出, sync_binlog
最安全的是设置是 1
,这也是MySQL 5.7.7
之后版本的默认值。但是设置一个大一些的值可以提升数据库性能,因此实际情况下也可以将值适当调大,牺牲一定的一致性来获取更好的性能。
binlog日志格式
binlog
日志有三种格式,分别为 STATMENT
、 ROW
和 MIXED
。
在
MySQL 5.7.7
之前,默认的格式是STATEMENT
,MySQL 5.7.7
之后,默认值是ROW
。日志格式通过binlog-format
指定。
-
STATMENT
:基于SQL
语句的复制(statement-based replication, SBR
),每一条会修改数据的sql语句会记录到binlog
中 。-
优点:不需要记录每一行的变化,减少了 binlog 日志量,节约了 IO , 从而提高了性能;
-
缺点:在某些情况下会导致主从数据不一致,比如执行sysdate() 、 slepp() 等 。
-
-
ROW
:基于行的复制(row-based replication, RBR
),不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了 。-
优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题 ;
-
缺点:会产生大量的日志,尤其是` alter table ` 的时候会让日志暴涨
-
-
MIXED
:基于STATMENT
和ROW
两种模式的混合复制(mixed-based replication, MBR
),一般的复制使用STATEMENT
模式保存binlog
,对于STATEMENT
模式无法复制的操作使用ROW
模式保存binlog
2. Redo log
记录事务对数据页做了哪些修改,REDO 为了重做对数据页(page)更改保存的信息。
InnoDB在每次提交时,没有办法把全部数据页刷到磁盘上,原因有下:
-
因为
Innodb
是以页
为单位进行磁盘交互的,而一个事务很可能只修改一个数据页里面的几个字节,这个时候将完整的数据页刷到磁盘的话,太浪费资源了! -
一个事务可能涉及修改多个数据页,并且这些数据页在物理上并不连续,使用随机IO写入性能太差!
因此 mysql
设计了 redo log
, 具体来说就是只记录事务对数据页做了哪些修改,这样就能完美地解决性能问题了(相对而言文件更小并且是顺序IO)
redo log 包括两部分:一个是内存中的日志缓冲( redo log buffer ),另一个是磁盘上的日志文件( redo logfile)。mysql 每执行一条 DML 语句,先将记录写入 redo log buffer,后续某个时间点再一次性将多个操作记录写到 redo log file。这种 先写日志,再写磁盘 的技术就是 MySQL里经常说到的 WAL(Write-Ahead Logging) 技术。
在计算机操作系统中,用户空间( user space )下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间( kernel space )缓冲区( OS Buffer )。因此, redo log buffer 写入 redo logfile 实际上是先写入 OS Buffer ,然后再通过系统调用 fsync() 将其刷到 redo log file中,过程如下:
mysql
支持三种将 redo log buffer
写入 redo log file
的时机,可以通过 innodb_flush_log_at_trx_commit
参数配置,各参数值含义如下:
3. Undo log
undo log
主要记录了数据的逻辑变化,比如一条 INSERT
语句,对应一条DELETE
的 undo log
,对于每个 UPDATE
语句,对应一条相反的 UPDATE
的 undo log
,这样在发生错误时,就能回滚到事务之前的数据状态, undo log
也是 MVCC
(多版本并发控制)实现的关键。