Mysql日志系统之binlog

Mysql日志系统之binlog

MySQL从整体来看,分为两层,一层是Server层,还有一层是引擎层。redo log是InnoDB引擎特有的日志,而Server层也有自己的日志,那就是binlog(归档日志)。

为什么需要两份日志?

MySQL的原生引擎是MyISAM,但是MyISAM只有binlog,而没有redo log这个功能,binlog日志只能用于归档,没有crash-safe的能力,所以就引入了InnoDB引擎,而redo log是InnoDB引擎特有的。

redo log和binlog的不同点:
1.redo log是InnoDB引擎特有的,而binlog是server层实现的,MySQL的所有引擎都可以使用。
2.redo log是循环写的,当redo log文件快被写完的时候,他会覆盖在检查点之前的日志,而binlog文件写到一定大小之后,会切换到下一个binlog文件,而且一个事务的binlog,一定是被写在同一个文件里的,不会被分割。
3.binlog是逻辑日志,记录的是语句的原始逻辑,如“给ID=10这一行的a字段加2”,而redo log记录的是物理日志,记录的是某个数据页上做了什么修改。

binlog的写入策略:

事务在执行过程中,先把日志写到binlog cache里,当事务提交的时候,再把binlog cache写入到binlog文件里,而写入到binlog文件也有两步,write(文件系统的page cache)和fsync(持久化到磁盘)。写到磁盘,没有持久化,物理上是在文件系统的page cache里,write就是指把日志写入到文件系统的page cache,并没有把数据持久化到磁盘,所以速度比较快,而fsync,才是将数据持久化到磁盘的操作,一般情况下,我们认为fsync才占磁盘的iops。

系统给binlog cache 分配了一片内存,每个线程一个,参数binlog_cache_size用于控制单个线程内binlog cache所占内存的大小,如果超过了这个参数规定的大小,就要暂存到磁盘。
事务提交的时候,执行器把binlog cache 里的完整事务写到入binlog中,并清空binlog cache。

binlog写入的策略是由参数参数sync_binlog控制的:
sync_binlog=0时,表示每次提交事务只write,不fsync
sync_binlog=1时,表示每次提交事务都执行fsync
sync_binlog=N(N>1),表示每次提交事务都write,但是累积N个事务后才fsync
比较常见的是将sync_binlog设置成为100-1000,但是风险就是如果主机发生异常重启,会丢失最近N个事务的binlog日志。

两阶段提交:
在这里插入图片描述

1.对一张表中的一行进行修改操作
2.引擎将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redo log处于prepare状态,告知执行器执行完成了,随时可以提交事务。
3.执行器生成这个操作的binlog,并将binlog写入
4.执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交(commit)状态,更新完成

如果不用两阶段提交:
1.先写redo log后写binlog,如在redo log写完之后,binlog还没有写,这时系统发生异常重启,这时候因为有redo log,数据可以恢复过来,但是binlog并没有生成,所以如果此时用binlog去恢复出一个库,那这个库肯定是和原库不一致的。
2.先写binlog,再写redo log,如果先把binlog写完,redo log还没有写,这时候数据库异常重启,由于redo log没有写,所以这个事务无效,但是binlog已经写完了,如果用binlog去恢复库,那也会发生和原库不一致的问题。

那如果使用两阶段提交,是否就能解决这个问题了呢?
答案是

两阶段提交,只是缩短了redo log提交和binlog提交之间的间隙,如果是在这个间隙时间发生异常重启,那还是会导致不一致的问题,但是这个概率小之又小。

发布了13 篇原创文章 · 获赞 2 · 访问量 459

猜你喜欢

转载自blog.csdn.net/qq_38114620/article/details/100662948