MySQL checkpoint机制详解
MySQL为了保证数据会做很多checkpoint动作。特别是InnoDB采用Write Ahead Log策略来防止宕机导致的数据丢失:即事务提交时,先写重做日志,再修改内存数据页的方式脏数据刷新等。除此之外,还有服务重新启动。
checkpoint是为了解决哪些问题呢?
对于数据需要频繁更新的场景,要实时更新,对于MySQL来说,只处理IO,就能把性能耗尽。
Redo日志大小也是有限的,通过刷新策略,可以更有效的重复使用文件,不需要开辟新的空间。
缓冲区大小有限。数据不刷到硬盘,对于查询业务,命中率越来越小。
数据库宕机,崩溃恢复期间,需要从上次的检查点进行恢复,使得效率提升。
物理备份日志点。
InnoDB引擎通过LSN(Log Sequence Number)来标记版本,LSN是日志空间中每条日志的结束点,用字节偏移量来表示。每个Page有LSN,每个Redo log有LSN,每个checkpoint也有LSN。
checkpoint会对哪些MySQL实体做操作?
Dirty page:InnoDB缓冲池中已经在内存中更新的页面,其中的更改还没有写入(刷新)到数据文件。
Flush:将已缓冲在内存区域或临时磁盘存储区域中的数据库文件的更改写入。
Redo log:数据更改信息记录文件。
从官方提供的说明中checkpoint分为两个:
Fuzzy checkpoint:进行部分脏页的刷新,有效循环利用Redo日志。
Sharp checkpoint:发生在关闭数据库时,将所有脏页刷回磁盘。
通过以上两个方式,在不同的情况下触发checkpoint:
1) flush_lru_list
2)Dirty Page
刷新比率
innodb_max_dirty_pages_pct:
InnoDB会尝试从缓冲池中刷新数据,这样脏页的百分比就不会超过这个值。innodb_max_dirty_pages_pct默认90%。innodb_max_dirty_pages_pct_lwm:
定义低水位标记,表示启用预冲洗以控制脏页比率的脏页百分比。0值将完全禁用预刷新行为。配置的值应该总是低于innodb_max_dirty_pages_pct的值。
innodb_flush_neighbors
innodb_lru_scan_depth
innodb_io_capacity
设置适用于所有的缓冲池实例。当刷新脏页时,I/O容量将平均分配给缓冲池实例。
注意,如果刷新落后,缓冲池的刷新速率可能会超过InnoDB可用的I/O容量,这是由innodb_io_capacity设置定义的。innodb_io_capacity_max值定义了这种情况下的I/O容量上限,这样I/O活动的峰值不会占用服务器的整个I/O容量。一般设置有不同的硬盘类型配置 SAS 200~1000 ,SSD 2000~5000 ,PCI-E 10000-50000
3)Adaptive Flushing
当产生大量写密集型工作负载时,可能会导致吞吐量的突然变化。当InnoDB Redo日志文件满了,就会出现一个Sharp checkpoint,导致临时的吞吐量降低。即使innodb_max_dirty_pages_pct阈值未达到,也会出现这种情况。
innodb_adaptive_flushing_lwm变量定义了Redo日志容量的低水位标志。当超过该阈值时,启用自适应刷新(Adaptive Flushing)。
4)限制空闲期间的缓冲区刷新
在空闲期间限制页面刷新可以帮助延长固态存储设备的寿命,但其的副作用可能包括在长时间的空闲期间之后更长的关闭时间以及在服务器发生故障时更长的恢复时间等问题。
5)Redo 日志
Redo日志在物理上表示为一组文件,通常命名为ib_logfile0和ib_logfile1。重做日志中的数据按照受影响的记录进行记录,这些数据统称为重做。重做日志的数据通过不断增加的LSN值表示。
用于记录数据修改后的记录,顺序记录。
在崩溃恢复期间使用的基于磁盘的数据结构,用于纠正不完整事务写入的数据。
Redo日志的磁盘布局受配置选项innodb_log_file_size、innodb_log_group_home_dir和innodb_log_files_in_group的影响。重做日志操作的性能还受到日志缓冲区的影响innodb_log_buffer_size。
在崩溃恢复期间,InnoDB需查找一个写入日志文件的检查点。LSN出现在数据库的磁盘映像之前对数据库的所有修改,之后InnoDB从检查点扫描日志文件,将日志修改应用到数据库。
Innodb_redo_log_archive_dirs重做日志进行归档,主要考虑到备份操作进行时,复制重做日志记录的备份实用程序有时可能无法跟上重做日志生成的速度,从而导致重写重做日志记录而丢失这些记录。除此之外也可以作为数据恢复的日志记录。
6)常见检查点压力下的日志
出现这个page_cleaner的问题是脏页产生的太快,导致页面清理程序清理不过来。
目前解决方式,可以组合以下参数进行调整:
innodb_lru_scan_depth 值设置小。
innodb_io_capacity,innodb_io_max_capacity 合理设置。
innodb_max_dirty_page_pct 也设置的小一些。
innodb_adaptive_hash_index 关闭。
对于MySQL的checkpoint机制来说,是对IO和内存做了平衡操作。
通过调节参数,对于不同的应用系统,都是提升性能的一种方式,普遍情况下采取默认方式。
另一个思路:重做日志可以无限增大,磁盘足够大,同时缓冲池足够大,能够缓存所有数据,那么就不需要将缓冲池中的脏页频繁刷新。
墨天轮原文链接:https://www.modb.pro/db/99807?sjhy(复制到浏览器或者点击“阅读原文”立即查看)