MySQL数据库日志解析
重做日志(redo log)
重做日志是InnoDB存储引擎产生的,非MYSQL数据库的上层产生,用于实现事务的持久性。日志分为两个部分:一是内存中的重做日志缓存,是易丢失的;二是重做日志文件,是持久的。重做日志是物理格式日志,其记录的是对于每个页的修改。
InnoDB存储引擎通过Force Log at Commit机制实现事务的持久性。即当前事务的所有日志写入到重做日志文件进行持久化后,事务的commit操作才算完成。
重做日志文件基本上都是顺序写的,在数据库运行时不需要对redo log文件进行读取操作。
为了确保每次日志都能写入日志文件,在每次将重做日志缓冲写入重做日志文件后,都需要执行一次fsync操作。
InnoDB引擎允许用户手动设置非持久性的情况发生,以此提高数据库的性能。即当事务提交时,日志不写入日志文件,而是在等待一个周期后再执行fsync操作,但宕机时,会丢失最后一段时间的事务。
参数innodb_flush_log_at_trx_commit来控制重做日志刷新到磁盘的策略。默认为1,即每次事务提交时必须执行一次fsync操作,2表示事务提交时不进行fsync操作,而是在Master Thread中进行,每一秒进行一次fsync操作,在这种情况下,当数据库宕机但是操作系统没有宕机时,并不会丢失最后一部分事务。
通过设置上面的参数可以提高数据库性能, 但是丧失了数据的ACID特性。
重做日志记录了事务的行为,可以很好地通过其对页进行“重做”操作。但是事务有时还需要回滚,这时候就需要undo日志。
日志块(log block)
在InnoDB存储引擎中,重做日志缓存、重做日志文件都是512字节块的方式进行保存的,成为重做日志块(redo log block)。因为和磁盘扇区大小一致,因此重做日志的写入可以保证原子性。
重做日志块由日志块header,日志本身,日志块tailer三部分组成。重做日志头占用12字节,日志尾占用8字节,日志本身可以存储492字节。
二进制日志(bin log)
二进制日志是MYSQL数据库上层产生的,任何存储引擎对于数据库的更改都会产生二进制文件,用来进行POINT-IN-TIME(PIT)的恢复,以及主从复制环境的建立。二进制日志一种逻辑日志,其记录的是对应的SQL语句。并且其只在只在事务提交后才会写入一次。
undo log
undo log是为了事务回滚而设计的,事务需要回滚,为了恢复到原来的状态,因此InnoDB存储引擎不但会产生重做日志,而且还会产生一定量的undo日志。这样,如果用户执行事务失败了,或者用户执行了rollback语句,则依靠undo日志可以将事务恢复到原来的状态。
存放位置:重做日志是放在重做日志文件里,而undo日志是放在数据库内部的一个特殊段(segment)中,这个段称为undo段。undo段存在于共享空间表中。
undo日志并不是物理日志,并不是物理的将数据库恢复到事务之前的状态。undo日志是逻辑日志,是从逻辑上将数据库恢复到事务之前的状态。为什么不是物理的?(物理的意思是:将数据库页恢复到之前的状态)。因为数据库可能面临数十、数百上千的并发事务,如果将物理的页恢复到之前的状态,那么会对其他事务造成干扰,其他事务对页的操作也会被回滚掉。因此,undo日志是逻辑上的日志,例如:对于每个insert,InnoDB存储引擎都会通过完成一个DELETE来回滚;对于每个DELETE,都会完成一个INSERT。对于一个UPDATE,会执行相反的UPDATE,把原来的信息给恢复回来。
除了有回滚事务的作用,undo log还有个作用是MVCC,多版本并发控制,通过MVCC来实现非锁定读。
在用户读取一行记录时,如果该行记录已被其他事务占用,当前事务可以通过undo读取此行记录之前的版本信息,从而实现非锁定读。
最后重要一点:undo log也会产生重做日志,因为undo log也需要进行持久性的保护。
管理:innoDB存储引擎对undo的管理同样采用段的方式,也就是说,存储undo日志的是段,段中还有段。
最外层叫回滚段(rollback segment),里层叫undo log segment,最开始的时候(InnoDB1.1版本之前(不包括1.1版本),只有一个rollback segment。后来又增加了,1.1版本开始InnoDB支持最大128个rollback segment。
每个rollback segment中有1024个undo log segment,因此在InnoDB1.1版本之前,只支持同时在线事务限制为1024。InnoDB1.1版本之后,支持最大128个rollback segment,因此,同时在线事务限制为128*1024个。
需要特别注意的是:事务在undo log segment分配页并写入undo log的这个过程中同样需要写入重做日志。当事务提交时,InnoDB存储引擎会做一下两件事情:1. 将undo log放入列表中,供以后的purge操作。2. 判断undo log所在的页是否可以重用,若可以分配给下个事务使用。