MySQL日志系统

当我们在MySQL客户端执行更改数据库的操作时,就会牵扯到日志系统了。如我们使用最多的存储引擎InnoDB而言,里面就会用到:redo log (重做日志)和 binlog(归档日志)。下面主要介绍一下这两种日志的区别与联系:

redo log

在MySQL里,如果我们要执行一条更新语句。执行完成之后,数据不会立马写入磁盘,因为这样对磁盘IO的开销比较大。MySQL里面有一种叫做WAL(Write-Ahead Logging),就是先写日志在写磁盘。就是当有一条记录需要更新的时候,InnoDB 会先写redo log 里面,并更新内存,这个时候更新的操作就算完成了。之后,MySQL会在合适的时候将操作记录 flush 到磁盘上面。当然 flush 的条件可能是系统比较空闲,或者是 redo log 空间不足时。

redo log 文件的大小是固定的,比如可以是由4个1GB文件组成的集合。如下图所示:


write pos 是当前要写入日志的位置,当写到末尾时,会重新到文件头部开始写入。checkpoint 是当前待擦除的位置,以此循环反复利用这 4GB 的空间。

有了 redo log,即时数据异常宕机,重启时也不会丢失已经提交的数据,这个能力叫做 crash-safe

binlog

通过MySQL的架构可以看出,MySQL服务端主要分为2大块:Server层引擎层。redo log 本身是 InnoDB所特有的日志,而Server 层也有自己的日志,那就是binlog。至于为什么会有两种日志,这就是历史原因了。最开始,MySQL原生的存储引擎是MyISAM。它本身不支持事务的特性,而InnoDB 是另外一家公司以插件的形式开发的,为了支持事务等特性,引入了 redo log。两者主要有以下区别:


结合到update 语句中,如:对ID=2的这一行的c 值进行更改,执行流程如下所示:


从上面的执行流程可以看出,对于redo log 的写入拆成了 2 个步骤,这就是 两阶段提交

总结

从上面的描述可以看出,redo log 可以用于保证 crash-safe 的能力。

1、在生产上,建议 innodb_flush_log_at_trx_commit 设置成 1,可以让每次事务的 redo log 都持久化到磁盘上。保证异常重启后,redo log 不丢失。

2、建议 sync_binlog 设置成 1,可以让每次事务的 binlog 都持久化到磁盘上。保证异常重启后,binlog 不丢失。


参考:《极客时间:MySQL实战》、《高性能MySQL》