mysql 的日志文件

mysql底层是有三种日志文件:undo、redo、binlog,这里我们是以InnoDB存储引擎为例的,为什么要牵扯去存储引擎呢,因为undo、redo是属于InnoDB存储引擎的,binlog才是属于mysql server的日志文件

为什么要这三种日志文件呢?

这里我们通过sql语句:update student name = ‘xx’ where id = 1;
来分析一下着三种日志文件的作用

首先我们都知道在InnoDB底层有个关键的缓存池Buffer Pool,在我们执行 update student name = ‘xx’ where id = 1;时也是通过修改缓冲池Buffer Pool的值来进行的,我们通过下面的流程图来分析一下这个原理:
这里主要流程我们可以分为如下几步:

  1. 加载磁盘文件到 Buffer Pool 缓冲池中
  2. 将未修改的数据写入undo日志中,作用:便于数据回滚
  3. 更新缓存Buffer Pool 的数据
  4. 写入redo日志,redo日志则是记录了对哪个数据做了修改
  5. 准备提交事务将redo日志写入磁盘
  6. 准备提交事务将binlog日志写入磁盘(binlog日志记录对哪个数据做了修改,修改结果是什么)
  7. 将binlog更新的文件名和更新文件的位置写入redo,并在redo log添加commit标记
  8. IO线程随机将 Buffer Pool 缓冲池中的数据刷入磁盘

    为什么一个简单的更新操作在mysql底层会弄的这么复杂呢?这里我们来简单分析一下

undo日志

-这是我们对数据回滚的依赖

Buffer Pool缓存池

这个很容易理解,任何和磁盘有关的操作性能都是极低的所以,所以mysql会引入Buffer Pool,首先是更新缓存,非常快,最后在空闲的时候通过后台IO随机更新到磁盘。

redo日志

redo日志记录了修改后的值,防止我们数据丢失,假如我们修改了Buffer Pool缓存中的值,还没有来得及刷新磁盘中的数据,数据库宕机了,那么Buffer Pool缓存中的数据丢失不是让磁盘中这一条数据成了脏数据吗?但是因为有redo日志,可以通过redo日志恢复所以是不要紧的。redo在设置中其实是有几种刷盘策略的,这里我们可以简单的了解下:

  1. 他是通过参数innodb_flush_log_at_trx_commit配置的
  2. 当参数为0时,提交事务不会将redo日志强制刷入磁盘
  3. 当参数为1时,提交事务成功一定会将redo日志写入磁盘
  4. 当参数为2时,提交事务时将redo日志写入os cache缓存中,1秒后写入磁盘

mysql数据库log字段 mysql logbuffer_缓存

这里三个参数建议是设置为1,强制写入磁盘,虽然对性能会有影响,但是可以保证数据的不丢失

binlog日志

对于binlog日志其实也是有个参数控制刷盘策略的,就是 sync_binlog,默认为0表示不是直接写入磁盘,也是先写入os cache缓存中,所以这里建议是吧sync_binlog参数设置为1,强制在提交事务的时候写入磁盘

为什么最后会在redo日志中写入commit标记

这里是为了保证binlog和redo日志的一致性,假设redo日志刚刚写入磁盘文件后mysql宕机了,不会因为redo日志有数据而binlog没有数据产生数据不一致问题,因为redo日志文件没有最终标记commit,所以这次事务是提交失败的