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的值来进行的,我们通过下面的流程图来分析一下这个原理:
这里主要流程我们可以分为如下几步:
- 加载磁盘文件到 Buffer Pool 缓冲池中
- 将未修改的数据写入undo日志中,作用:便于数据回滚
- 更新缓存Buffer Pool 的数据
- 写入redo日志,redo日志则是记录了对哪个数据做了修改
- 准备提交事务将redo日志写入磁盘
- 准备提交事务将binlog日志写入磁盘(binlog日志记录对哪个数据做了修改,修改结果是什么)
- 将binlog更新的文件名和更新文件的位置写入redo,并在redo log添加commit标记
- IO线程随机将 Buffer Pool 缓冲池中的数据刷入磁盘
为什么一个简单的更新操作在mysql底层会弄的这么复杂呢?这里我们来简单分析一下
undo日志
-这是我们对数据回滚的依赖
Buffer Pool缓存池
这个很容易理解,任何和磁盘有关的操作性能都是极低的所以,所以mysql会引入Buffer Pool,首先是更新缓存,非常快,最后在空闲的时候通过后台IO随机更新到磁盘。
redo日志
redo日志记录了修改后的值,防止我们数据丢失,假如我们修改了Buffer Pool缓存中的值,还没有来得及刷新磁盘中的数据,数据库宕机了,那么Buffer Pool缓存中的数据丢失不是让磁盘中这一条数据成了脏数据吗?但是因为有redo日志,可以通过redo日志恢复所以是不要紧的。redo在设置中其实是有几种刷盘策略的,这里我们可以简单的了解下:
- 他是通过参数innodb_flush_log_at_trx_commit配置的
- 当参数为0时,提交事务不会将redo日志强制刷入磁盘
- 当参数为1时,提交事务成功一定会将redo日志写入磁盘
- 当参数为2时,提交事务时将redo日志写入os cache缓存中,1秒后写入磁盘
这里三个参数建议是设置为1,强制写入磁盘,虽然对性能会有影响,但是可以保证数据的不丢失
binlog日志
对于binlog日志其实也是有个参数控制刷盘策略的,就是 sync_binlog,默认为0表示不是直接写入磁盘,也是先写入os cache缓存中,所以这里建议是吧sync_binlog参数设置为1,强制在提交事务的时候写入磁盘
为什么最后会在redo日志中写入commit标记
这里是为了保证binlog和redo日志的一致性,假设redo日志刚刚写入磁盘文件后mysql宕机了,不会因为redo日志有数据而binlog没有数据产生数据不一致问题,因为redo日志文件没有最终标记commit,所以这次事务是提交失败的