1.MySQL日志
MySQL日志包括:错误日志、慢查询日志、二进制日志(bin Log)、重做日志(redo Log)、回滚日志(undo Log)等。其中redo Log、undo Log、bin Log最为重要,面试中经常会问到。
**redo Log:**它是物理日志,记录内容是“在某个数据页上做了什么修改”,属于 InnoDB
存储引擎。保证事务的持久性、使MySQL有崩溃恢复能力。
MySQL的读写操作都是基于缓冲池的,更改缓冲池中一条数据,该数据落盘前服务器或者数据库宕机会造成更改数据的丢失,磁盘文件的数据不是最新数据。redo Log的崩溃恢复就是恢复这部分未落盘的和磁盘数据不一致的修改数据。
为什么引入redo Log?
情况一:如果不引入redo Log,直接对修改记录刷盘(左边绿色箭头)。
直接对修改记录刷盘事随机写,性能低且每次都是逐条刷到磁盘,影响数据库性能。
情况二:为了提升性能,引入了redo Log。落盘策略右边三个蓝色。
第一步:事务提交后,将日志记录逐条写入日志缓冲,为后续批量写缓存数据
第二步:将日志缓冲中日志写入OS Cache,每次写优化为批量写,提升操作系统性能。
第三步:操作系统fsync()决定刷盘时机,或者MySQL控制fsync()决定刷盘时机
情况二是以安全换性能,因为分阶段提交数据会有数据丢失风险。
在第一步事务提交时,将RedoLog记录写入缓冲池,MySQL就认为事务完成(自认为数据安全了)。
在第二步,如果日志缓冲中的日志记录写入(write())入OS Cache之前,数据库或操作系统崩溃,数据就会丢失
在第三步,如果OS Cache数据fsync()磁盘之前,操作系统崩溃,数据会崩溃。
redo Log刷盘策略:**
MySQL通过innodb_flush_log_at_trx_commit参数控制redo Log不同刷盘策略。具体如下图所示。
刷盘策略一:innodb_flush_log_at_trx_commit=0
每隔一秒,才将Log Buffer中的数据批量write入OS cache,同时MySQL主动fsync。
这种策略,如果数据库奔溃,有一秒的数据丢失。
刷盘策略二:
每次事务提交,都将Log Buffer中的数据write入OS cache,同时MySQL主动fsync。
这种策略,是InnoDB的默认配置,为的是保证事务ACID特性。
刷盘策略三:
每次事务提交,都将Log Buffer中的数据write入OS cache;
每隔一秒,MySQL主动将OS cache中的数据批量fsync。
这种策略,如果操作系统奔溃,最多有一秒的数据丢失。
redo Log如何完成崩溃恢复?
MySQL数据库采用先写日志(write log first)策略,来解决数据丢失问题。redo Log通过不同的刷盘策略来保证日志文件(修改操作)一定落盘,日志一旦落盘就不用担心数据丢失了。
磁盘数据页没损坏:
直接使用redo Log恢复,每条redo Log记录由“表空间号+数据页号+偏移量+修改数据长度+具体修改记录”构成。加载redo Log更改相应数据页数据。
**磁盘数据页损坏:**双写机制
当缓冲池向磁盘刷一半,服务器宕机了,此时磁盘数据只更新半。此时数据页损坏了。当使用redo Log进行数据恢复时,通过数据页Fial字段发现数据页损坏,哪么直接通过该日志恢复磁盘数据是有问题的。因为,同一个操作会执行两次(缓冲池刷盘一次,redolog回复一次)。此时可以引入双写机制。
双写机制将待落盘数据页分两次,前后写入磁盘。
当第一次写入磁盘double writer Buffer失败,那么磁盘数据页是完整的,可以使用redo log恢复。
当第二次写入磁盘double writer Buffer成功,第二次写入磁盘数据页失败,此时磁盘数据页破损。但是磁盘double writer Buffer有完整数据,可以直接覆盖磁盘数据页数据。不需要使用redo log恢复。
bin Log:它是逻辑日志,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”,属于MySQL Server 层。MySQL的数据备份、主备、主从、主主都需要bin Log来同步数据,保证数据一致。
undo Log:事务回滚,以回滚段的形式存在。通过数据行隐藏段中的roll_pointer指针拉链存在