Mysql binlog和redolog

Mysql binlog和redolog

原创: 怀风  光明和黑暗互相吸引  5天前
binlog 文件

什么是binlog


binlog 全称为 (binary log) ,记录了对MYSQL数据库执行的所有操作语句(不包括SELECT,SHOW这类操作,因为这类型的操作不会对数据本身做修改),但是如果操作本身没有对数据库进行修改,那么该操作也会被记录入数据库。



如下表:test


idname
1test
执行如下sql,是不对test表做数据修改,但是也会记录该操作
update test 
set
 name 
=
 
1
 
where
 id 
=
 
2
binlog日志的作用

恢复:数据恢复需要binlog
复制:与恢复原理类似,主要用来做主从复制,master->slave
审计:用户可以通过二进制日志中的信息来进行审计,判断是否又对数据库进行注入攻击
binlog日志的格式

从mysql5.1以后,开始引入binlog_format参数用于设置binlog的格式

statement:记录逻辑sql语句(如果使用 read commited事务隔离级别,会出现类似丢失更新的现象,导致主从复制出现问题,由于事务未提交且没有gaplock锁 binlog日志在缓冲中未写入binlog文件,写入文件顺序是事务提交的顺序.可能会导致同步是否顺序不一致)
row:不在记录简单的sql语句(能够解决statement在read committed事务隔离级别遇到问题,但是日志文件会变得更大)
mixed:mysql默认会采用statement格式,但是在一些特定情况下会使用row(相当于两者混合,自适应使用)
binlog日志的写入

在默认情况下,binlog日志并不是每次写的时候就同步到磁盘的(类似于缓冲写,先写缓存,在同步到磁盘),但是如果在此时数据库发生宕机,再会给恢复和复制带来一些问题,有些数据可能没写入binlog,导致最后一部分数据丢失,这个时候syncbinlog参数就可以解决这个问题,syncbinlog这个参数,代表每次缓存写多少次日志同步到磁盘,如果参数设为1,则不写缓存每次操作直接同步到磁盘,但是这样会对系统IO产生一定影响,但是设置为1同时还有一种影响,就是一个事务还未提交前已经将该条日志记录到了磁盘,如果这时候事务还没提交数据库就宕机了,再回复的时候,未提交的事务并没有回滚,就会出现问题,在这种情况下可以通过设置,innodbsupportxa=1来解决
这里可能有人会觉得开启binlog日志会对数据库性能有影响,但是在官方手册中标识,性能损耗只有1%,但考虑到可用性,数据的恢复和复制,这点性能的损耗还是可以接受的
redo log 文件

什么是redo log

记录了对MYSQL数据库innodb存储引擎,记录了innodb存储引擎的事务日志,用于恢复数据。每个innodb存储引擎至少有一个redo log文件组,每个文件组中至少有两个redo log文件,每个文件大小一致,并以循环写入的方式运行.并且redo log不是直接写到磁盘,是先写入redo log缓存,在刷盘到磁盘,当两个文件都写满的时候,会进行checkpoint,将文件1的内容抹除,如图

redo log 和 binlog的区别

这里可能大家会有疑问,binlog可以恢复,那么要redo log有什么意义呢

redo log 是innodb引擎特有的,binlog是mysql的server层实现的,所有引擎都可以使用
redo log 是物理日志,记录了在某个数据页的修改,binlog是逻辑日志,记录的是这条记录的修改逻辑
redo log 是循环写的,空间固定会用完,binlog是可以追加写入的,"追加写"是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志
redo log 的大小不宜设置的过大或者过小,过小的话会导致频繁的checkpoint导致性能抖动,太大则恢复会需要更长的时间
两阶段提交

为了保证恢复数据时的状态准确性,维护逻辑一致性,采用两阶段提交,例如一次更新数据,如图

根据binlog的特性,我们可以知道binlog是在事务提交前写入,如果事务还未提交的时候,这个时候binlog已经写入了,但是数据库发生了异常宕机,那么根据binlog来恢复,就会把未提交的事务给恢复到库中,造成脏数据,而采用两阶段提交,这个时候我们看到redo log处于prepare阶段,binlog已经写了日志 则可以对未提交事务的脏数据做处理,防止恢复的时候出现脏数据
如果redo log 里面的事务只有完整的prepare,则判断对应事务binlog是否完整存在,如果是,则提交事务,如果不是回归事务
redo log 的写入

通过设置参数innodbflushlogattrx_commit的值来控制将缓存中的redo log写入磁盘,0代表提交事务时,不将redo log写入磁盘,而是等每次主线程刷新,1和2的区别在于,1表示在commit的时候将redo log从缓存中同步到磁盘,即伴有fsync的调用,2表示将redo log异步写到磁盘,即写到文件系统的缓存中,因此不能完全保证执行commit的时候会一定写入磁盘,为了保证事务的ACID中的持久性,必须将此参数设置为1,也就是每当有事务提交时,必须保证日志写入磁盘
这里要注意,如果有两个事务,如果事务A提交,事务B只写了redo log那么事务B的redo log也会被刷到磁盘上

阅读原文

微信扫一扫
关注该公众号

更多内容vip可查看