mysql的三大日志文件binlog/redolog/undolog
why(背景):
数据写入的核心过程。例子:“update T set c=c+1 where ID=2;”
1、执行器从存储引擎中,查找主键ID=2的数据(存储引擎使用树搜索找到这一行)。如果ID=2的数据页在内存中,则直接返回;否则,从磁盘中找到对应的数据页,然后加载到内存中,然后返回;
2、执行器拿到存储引擎返回的数据后,将这行数据的C数值+1,则原来数值将从N,变为N+1;然后将数值,通过存储引擎的接口写回;
3、存储引擎将修改后的行数据写入内存中,同时将这个更新操作记录写入redolog里面,此时redolog出入prepare状态。然后告诉执行器执行完毕,随时可以提交事务;
4、执行器生成这个操作的binlog记录,并将其写入binlog的磁盘文件中;
5、执行器通过存储引擎的事务接口提交,存储引擎将刚才的redolog状态改为commit,更新完成;
what:
binlog:
属于server层的归档日志,以二进制形式记录语句的原始逻辑。注意:binlog没有crash-safe的能力。
其记录mysql的写入性操作日志,以二进制形式写入磁盘。是server层的逻辑日志,所以所有使用mysql
数据库的都会记录 binlog
日志。
逻辑日志:可以理解为sql语句;
物理日志:可以理解为数据页变更;
binlog采用追加写入的方式,通过max_binlog_size设置文件大小。达到指定大小后,会生成新的文件。
主要使用场景:主从同步,数据恢复。
主从复制 :在 Master
端开启 binlog
,然后将 binlog
发送到各个 Slave
端, Slave
端重放 binlog
从而达到主从数据一致。
数据恢复 :通过使用 mysqlbinlog
工具来恢复数据。
刷盘时机:
通过 sync_binlog
参数控制,取值范围为0~N。
0:不去强制要求,由系统自行判断何时写入磁盘;
1:每次 commit
的时候都要将 binlog
写入磁盘;
N:每N个事务,才会将 binlog
写入磁盘。
日志格式:分别为 STATMENT
、 ROW
和 MIXED。具体见:
redo log
mysql使用redo-log来保证事务的一致性(只要事务提交成功,那么对数据库做的修改就被永久保存下来了)。
最简单的保证事务的一致性,就是每次commit时就将所有的数据页刷到磁盘上,但是这样性能会有很大的挑战,主要原因为:
1、Innodb
是以 页
为单位进行磁盘交互的。有可能1次commit仅仅修改了数据页上的几个字节,而需要完整的将数据页写入,比较浪费;
2、有可能1个commit会修改多个数据页,不仅数据页不连续,而且每个数据页都是微改动;
redo-log仅记录commit对数据做的哪些变更,就能完美地解决性能问题了(相对而言文件更小并且是顺序IO)。
记录流程:
先将数据页的修改变更写入redo log buffer;后续在特定时刻,将多个操作刷盘到redo log file中(放在磁盘)。(这种先写日志,再写磁盘的技术就是MySQL里的WAL(Write-Ahead Logging)技术。)
数据写入机制:
mysql支持三种写入,可以通过 innodb_flush_log_at_trx_commit 参数配置
写入redo log file也是磁盘IO,但它是顺序IO,比从缓冲池将数据页随机IO到磁盘快很多。
记录形式:
redo log日志大小是固定的。Checkpoint 以前表示已经更新到磁盘的文件,write pos表示当前写的位置,如果两个指针相遇了,表示redo log已经满了,需要同步到磁盘中。如下图:
redo log
存在的意义主要就是降低对 数据页
刷盘的性能要求。
和binlog的区别:
undo log
使用undo-log来确保事务的原子性(指对数据库的一系列操作,要么全部成功,要么全部失败,不可能出现部分成功的情况) 。
工作原理:
主要记录了数据的逻辑变化(相反的)。比如一条 INSERT
语句,对应一条DELETE
的 undo log
,对于每个 UPDATE
语句,对应一条相反的 UPDATE
的 undo log
,这样在发生错误时,就能回滚到事务之前的数据状态。
undo log
也是 MVCC
(多版本并发控制)实现的关键。
参考文档:https://blog.csdn.net/qq_39751320/article/details/108903523