Innodb log与undo log

Innodb log

InnoDB 有两块非常重要的日志,一个是undo log,另外一个是redo log,前者用来保证事务的原子性以及InnoDB的MVCC,后者用来保证事务的持久性。

和大多数关系型数据库一样,InnoDB记录了对数据文件的物理更改,并保证总是日志先行,也就是所谓的WAL,即在持久化数据文件前,保证之前的redo日志已经写到磁盘。

LSN(log sequence number) 用于记录日志序号,它是一个不断递增的 unsigned long long 类型整数。在 InnoDB 的日志系统中,LSN 无处不在,它既用于表

示修改脏页时的日志序号,也用于记录checkpoint,通过LSN,可以具体的定位到其在redo log文件中的位置。

为了管理脏页,在 Buffer Pool 的每个instance上都维持了一个flush list,flush list 上的 page 按照修改这些 page 的LSN号进行排序。因此定期做redo

checkpoint点时,选择的 LSN 总是所有 bp instance 的 flush list 上最老的那个page(拥有最小的LSN)。由于采用WAL的策略,每次事务提交时需要持久化

redo log 才能保证事务不丢。而延迟刷脏页则起到了合并多次修改的效果,避免频繁写数据文件造成的性能问题。

由于 InnoDB 日志组的特性已经被废弃(redo日志写多份),归档日志(InnoDB archive log)特性也在5.7被彻底移除,本文在描述相关逻辑时会忽略这些逻辑。

另外限于篇幅,InnoDB崩溃恢复的逻辑将在下期讲述,本文重点阐述redo log 产生的生命周期以及MySQL 5.7的一些改进点。

InnoDB的redo log可以通过参数innodb_log_files_in_group配置成多个文件,另外一个参数innodb_log_file_size表示每个文件的大小。因此总的redo log大小为innodb_log_files_in_group * innodb_log_file_size。

Redo log文件以ib_logfile[number]命名,日志目录可以通过参数innodb_log_group_home_dir控制。Redo log 以顺序的方式写入文件文件,写满时则回溯到第一个文件,进行覆盖写。(但在做redo checkpoint时,也会更新第一个日志文件的头部checkpoint标记,所以严格来讲也不算顺序写)。

InnoDB日志文件

在InnoDB内部,逻辑上ib_logfile被当成了一个文件,对应同一个space id。由于是使用512字节block对齐写入文件,可以很方便的根据全局维护的LSN号计算出

要写入到哪一个文件以及对应的偏移量。

Redo log文件是循环写入的,在覆盖写之前,总是要保证对应的脏页已经刷到了磁盘。在非常大的负载下,Redo log可能产生的速度非常快,导致频繁的刷脏操作,

进而导致性能下降,通常在未做checkpoint的日志超过文件总大小的76%之后,InnoDB 认为这可能是个不安全的点,会强制的preflush脏页,导致大量用户线程

stall住。如果可预期会有这样的场景,我们建议调大redo log文件的大小。可以做一次干净的shutdown,然后修改Redo log配置,重启实例。

设置innodb log(设置 innodb日志路径、大小、组数)

innodb_data_home_dir=/dblog

innodb_log_group_home_dir=/dblog

innodb_log_file_size=1G

innodb_log_files_in_group=4

undo log

Undo log回滚日志是保存在共享表空间ibdata1文件里的,随着业务的不停的运转,ibdata1文件会越来越大,想要回收(收缩空间大小)极其困难和复杂,必须先将

mysqldump –A全库数据导出,然后删掉data目录,之后重新初始化安装,最后再把全库的SQL文件导入,这样才可实现ibdata1文件的回收。

在mysql5.6版本里,可以把undo log回滚日志分离到一个单独的表空间里;其缺点是不能回收(收缩)空间大小,直到mysql5.7版本才支持在线收缩。

但mariadb10.2中也支持此功能。

innodb_max_undo_log_size

innodb_undo_directory

innodb_undo_log_truncate

innodb_undo_logs

innodb_undo_tablespaces

发表评论

发表评论

*

沙发空缺中,还不快抢~