了解 MySQL 数据库的三大日志(redo log、undo log、binary log)
前言
MySQL 中有以下几种日志,包括:
-
redo log(重做日志)
-
undo log(回滚日志)
-
binary log(二进制日志)
-
error log(错误日志)
-
slow query log(慢查询日志)
-
general log(一般查询日志)
-
relay log(中继日志)
事务的特性:
-
原子性(Atomicity) :事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
-
一致性(Consistency):执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
-
隔离性(Isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
-
持久性(Durabilily):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
redo log 重做日志
可以知道在 MySQL 中只有 InnoDB 存储引擎是支持事务的,所以 redo log(重做日志)以及 undo log(回滚日志)是InnoDB 存储引擎独有的,这两种日志也叫做事务日志。在数据库中,当内存数据页跟磁盘数据页内容不一致的时候,则这个内存页为“脏页”。而当内存数据页与磁盘数据页内容一致时,则该内存页为”干净页“。
作用:
保证了事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。
内容:
物理格式的日志,记录的是物理数据页面的修改的信息,其redo log是顺序写入redo log file
的物理文件中去的。
什么时候产生:
事务开始之后就产生redo log,redo log的落盘并不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo log文件中。
什么时候释放:
当对应事务的脏页写入到磁盘之后,redo log的使命也就完成了,重做日志占用的空间就可以重用(被覆盖)。
undo log 回滚日志
作用:
保证数据的原子性,保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读
内容:
逻辑格式的日志,在执行undo的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,这一点是不同于redo log的。
什么时候产生:
事务开始之前产生undo log,undo 也会产生 redo 来保证undo log的可靠性
什么时候释放:
当事务提交之后,undo log并不能立马被删除,而是放入待清理的链表,由purge线程判断是否由其他事务在使用undo段中表的上一个事务之前的版本信息,决定是否可以清理undo log的日志空间。
MySQL中的Undo Log严格的讲不是Log,而是数据,因此他的管理和落盘都跟数据是一样的:
• Undo的磁盘结构并不是顺序的,而是像数据一样按Page管理
• Undo写入时,也像数据一样产生对应的Redo Log
• Undo的Page也像数据一样缓存在Buffer Pool中,跟数据Page一起做LRU换入换出,以及刷脏。
• Undo Page的刷脏也像数据一样要等到对应的Redo Log 落盘之后
bin log 二进制日志
binary log(binlog)是逻辑日志,记录的是语句原始的逻辑,不论什么存储引擎,只要发生了表数据的更新,都会产生 binlog日志。
作用:
用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。
用于数据库的基于时间点的还原。
内容:
逻辑格式的日志,可以简单认为就是执行过的事务中的sql语句。
但又不完全是sql语句这么简单,而是包括了执行的sql语句(增删改)反向的信息,也就意味着delete对应着delete本身和其反向的insert;update对应着update执行前后的版本的信息;insert对应着delete和insert本身的信息。
在使用mysqlbinlog解析binlog之后一些都会真相大白。
因此可以基于binlog做到类似于oracle的闪回功能,其实都是依赖于binlog中的日志记录。
什么时候产生:
事务提交的时候,一次性将事务中的sql语句(一个事物可能对应多个sql语句)按照一定的格式记录到binlog中。
这里与redo log很明显的差异就是redo log并不一定是在事务提交的时候刷新到磁盘,redo log是在事务开始之后就开始逐步写入磁盘。
因此对于事务的提交,即便是较大的事务,提交(commit)都是很快的,但是在开启了bin_log的情况下,对于较大事务的提交,可能会变得比较慢一些。
这是因为binlog是在事务提交的时候一次性写入的造成的,这些可以通过测试验证。
什么时候释放:
binlog的默认是保持时间由参数expire_logs_days配置,也就是说对于非活动的日志文件,在生成时间超过expire_logs_days配置的天数之后,会被自动删除。