mysql的日志分为三种,Undo-log,Redo-log和Bin-log。
InnoDB在mysql启动时,会创建一个BufferPool,这个缓冲池主要存放的就是Undo-log,Redo-log和Bin-log等日志,还有一些索引,锁,表数据等。
Undo-log:
我习惯把他成为回滚日志。在我们去修改某一条数据的时候,Undo-log会吧之前的数据也记录下来串成一个版本链。在表中,会有一个隐藏字段,叫roll_ptr,该字段存储的是Undo-log的地址,该地址引用的就是Undo-log中记录的上一次未修改的数据。通过该字段可以将这一条数据的修改记录穿成一个版本链。当然,Undo-log的日志一不是一直不会删除,mysql有一个专门的线程purger去进行维护。
Redo-log:
重做日志,我理解的Redo-log是和redis中的aof日志或者rde快照是差不多的,他们都是用来恢复数据的。不过,不同的是Redo-log是预写式日志,aof和rdb是当数据落在db中才去进行记录的。mysql的数据都是存在磁盘的,如果每次io都走磁盘的话效率就会十分低下,mysql官方基于如此,设计了一个BufferPoll缓存池。BufferPoll是基于内存操作的,相对于磁盘操作效率提升很明显。但是,如果在数据写到内存的时候服务器重启,当你恢复好的时候内存中的数据就会丢失。所以Redo-log诞生了。当写入数据的时候会先在Redo-log中存储。数据的存储顺序首先是Redo-log然后是内存最后是磁盘。既然Redo-log也是基于内存的,那么就也会有丢失风险。我们可以通过设置Redo-log的刷盘策略将风险降到最低。
Redo-log的刷盘策略由innodb_flush_log_at_trx_commit参数控制
0:每隔一段时间刷写一次日志到磁盘。(性能最高)
1:每一次提交事务都刷写一次磁盘(默认,最安全)
2:有事务提交的时候刷写一次磁盘
ps:Redo-log和Undo-log是InnoDB独有的
Bin-log:
二进制日志,会记录每一次除了select,show这类读操作的记录,如果使用了update语句就算该数据没有任何改变,bin-log也会记录下来。bin-log是mysql-server级别的日志,也就是所有存储引擎都可以用。bin-log日志在mysql8之后才会默认开启。Bin-log和redis的aof很像,他们都是无限追加的。当一个log文件写满后会创建一个新的log文件每个文件的命名方式是mysql-bin.000001,mysql-bin.000002......可以通过show binary logs查看bin-log日志文件.
Bin-log日志中共有segment,row和mixed三种格式。
segment记录的是每次修改的sql语句,但是这样会有一个问题比如下图这条sql
insert into `zz_users` values(11,"小王","男","12",sysdate());
当我们使用主从架构做同步的时候,当把这条sql拿到从机上执行时候就会造成主从的数据不一致。针对这种情况row诞生了。row记录的不是sql语句而是记录的修改的值,就是在那个分区下那一页的数据别修改掉了。但是这样的格式会造成binlog日志相对于segment的格式更加的大。
mixed格式就是segment和row的一个结合版,对于能复制的sql就使用segment进行记录,对于不能复制的sql就使用row的格式进行记录。