binlog要与redo log对比来看,这篇文章就通过两者的对比来说明binlog的功能。
binlog功能
二进制日志(binlog),其用来进行point in time(PIT 基于时间点的恢复)的恢复及主从复制(Replication)环境的建立。binlog也是一种恢复机制,其实现的是基于时间点的恢复,比如通过binlog将数据库恢复到某个时间点。
从表面上看其和重做日志非常相似,都是记录了对于数据库操作的日志。然而,从本质上来看,两者有着非常大的不同。
binlog工作过程
对于mysql的日志
在事务提交的时候,并不仅仅写redo log,还会记录binlog。
二进制日志(binary log、binlog)记录了对MySQL数据库执行更改的所有操作,但是不包括SELECT 和SHOW 这类操作,因为这类操作对数据本身并没有修改
问题1:为什么需要记录两份呢?
原因与mysql的基础架构有关。mysql支持多种存储引擎,那么redo log只是innodb引擎(存储引擎层)使用的,那么如何保证跨引擎的情况呢?在mysql的上层(mysql服务器层)还需要记录到binlog中。
oracle中就没有binlog,只用redo log,复制是基于redo log来做
问题2:如何保证redo log与bin log日志一致性
为什么要保证两者的一致性呢?是为了保证主从复制的一致性。
在这里面使用了mysql内部分布式事务
事务提交了
-
innodb redo log prepare log
第一步先写innodb redo log的prepare的日志,prepare只是写一个xid
-
write binary log file
第二步写mysql的binlog的日志
-
innodb redo log commit log
第三步写innodb redo log的commit日志
场景1::当事务提交的时候,如果prepare日志写入成功了,二进制日志写入成功了,但是第三步在写commit日志的时候,服务器down机了。
那么恢复的时候,可以检测到prepare log中记录了一个xid,binlog中也有这个xid,这两个log中都有这个xid,就说明这个事务一定要提交,不管第三步有没有这个commit log了。也就是说这个事务全部都执行完了,就差最后的commit语句了,那么再恢复的时候,只要执行commit就可以了。
场景2:如果只有第一步成功了,那么第二步失败了,那么整个事务就会rollback。
对比binlog和redo log
不同点1:
重做日志是在InnoDB 存储引擎层产生,而二进制日志是在MySQL 数据库的上层产生的,并且二进制日志不仅仅针对于InnoDB 存储引擎,MySQL数据库中的任何存储引擎对于数据库的更改都会产生二进制日志。
不同点2:
两种日志记录的内容形式不同。MySQL 数据库上层的二进制日志是一种逻辑日志,其记录的是对应的SQL 语句。而InnoDB存储引擎层面的重做日志是物理格式日志,其记录的是对于每个页的修改。
不同点3:
两种日志记录写入磁盘的时间点不同,二进制日志只在事务提交完成后进行一次写入。而InnoDB 存储引擎的重做日志在事务进行中不断地被写入(不断地写入redo log buffer,不断地刷新),这表现为日志并不是随事务提交的顺序进行写入的。
注意,这里是事务进行中就会向redo log buffer中不断写入了,如果最后事务回滚了,其会处理好LSN的;如果事务提交了,就是正常情况
二进制日志仅在事务提交时记录,并且对于每一个事务,仅包含对应事务的一个日志。而对于lnnoDB 存储引擎的重做日志,由于其记录的是物理操作日志,因此每个事务对应多个日志条目,并且事务的重做日志写入是并发的,并非在事务提交时写入,故其在文件中记录的顺序并非是事务开始的顺序。
不同点4:
比如说我一个事务更新一张几百万条记录的表,那么产生的binlog日志估计有几百M,那么我commit的时候就是commit这几百M的日志。这时候commit就会发生类似等待的效果(其在写binlog的日志)
假设redo log也是200M,但由于其每秒钟就会fsync一次,其在不停的写,所以并不会发生类似等待的效果
不同点5:
无论是写redo log,还是写binlog,都是先写缓存,再fsync到磁盘
redo log是写在redo log buffer中的
而binlog是写在binlog cache中的,binlog_cache_size,默认32K大小
比如说我一个大事务产生200M的日志,那么怎么办呢?装不下那就直接写到磁盘中去。
不同点6
InnoDB 存储引擎在启动时不管上次数据库运行时是否正常关闭,都会尝试进行恢复操作。因为重做日志记录的是物理日志,因此恢复的速度比逻辑日志,如二进制日志要快很多。
redo log中是幂等操作,而在binlog中,其操作并不是幂等的,比如insert在binlog中就不是幂等的