MySql学习(专项篇)内存数据落盘

整体思路分析

在这里插入图片描述

InnoDB内存缓冲池中的数据page要完成持久化的话,是通过两个流程来完成的,一个是脏页落
盘;一个是预写redo log日志。

保证数据的持久性

当缓冲池中的页的版本比磁盘要新时,数据库需要将新版本的页从缓冲池刷新到磁盘。但是如果
每次一个页发送变化,就进行刷新,那么性能开发是非常大的,于是InnoDB采用了Write Ahead
Log(WAL)策略和Force Log at Commit机制实现事务级别下数据的持久性。

WAL要求数据的变更写入到磁盘前,首先必须将内存中的日志写入到磁盘;
Force-log-at-commit要求当一个事务提交时,所有产生的日志都必须刷新到磁盘上,如果日志刷
新成功后,缓冲池中的数据刷新到磁盘前数据库发生了宕机,那么重启时,数据库可以从日志中 恢复数据。
为了确保每次日志都写入到重做日志文件,在每次将重做日志缓冲写入重做日志后,必须调用一
次fsync操作,将缓冲文件从文件系统缓存中真正写入磁盘。 可以通过 innodb_flush_log_at_trx_commit
来控制重做日志刷新到磁盘的策略。

脏页落盘

在数据库中进行读取操作,将从磁盘中读到的页放在缓冲池中,下次再读相同的页时,首先判断
该页是否在缓冲池中。若在缓冲池中,称该页在缓冲池中被命中,直接读取该页。否则,读取磁 盘上的页。

对于数据库中页的修改操作,则首先修改在缓冲池中的页,然后再以一定的频率刷新到磁盘上。
页从缓冲池刷新回磁盘的操作并不是在每次页发生更新时触发,而是通过一种称为CheckPoint的 机制刷新回磁盘。

CheckPoint检查点机制

CheckPoint是为了解决下面几个问题:

  1. 缩短数据库的恢复时间;
  2. 缓冲池不够用时,将脏页刷新到磁盘;
  3. 重做日志不可用时,刷新脏页

当数据库发生宕机时,数据库不需要重做所有的日志,因为Checkpoint之前的页都已经刷新回磁
盘。数据库只需对Checkpoint后的重做日志进行恢复,这样就大大缩短了恢复的时间。

当缓冲池不够用时,根据LRU算法(最少最近使用原则)会溢出最近最少使用的页,若此页为脏页,那么需要强制执行
Checkpoint,将脏页也就是页的新版本刷回磁盘。

当重做日志出现不可用时,因为当前事务数据库系统对重做日志的设计都是循环使用的,并不是让
其无限增大的。重做日志可以被重用的部分是指这些重做日志已经不再需要,当数据库发生宕机
时,数据库恢复操作不需要这部分的重做日志,因此这部分就可以被覆盖重用。如果重做日志还需
要使用,那么必须强制Checkpoint,将缓冲池中的页至少刷新到当前重做日志的位置。

CheckPoint分类

在InnoDB存储引擎内部,有两种Checkpoint,分别为:Sharp Checkpoint、Fuzzy Checkpoint

  1. sharp checkpoint:在关闭数据库的时候,将buffer pool中的脏页全部刷新到磁盘中
  2. fuzzy checkpoint:数据库正常运行时,在不同的时机,将部分脏页写入磁盘。仅刷新部分脏页
    到磁盘,也是为了避免一次刷新全部的脏页造成的性能问题。
fuzzy checkpoint

Fuzzy Checkpoint分为以下几种:

  1. Master Thread Checkpoint
  2. FLUSH_LRU_LIST Checkpoint
  3. Async/Sync Flush Checkpoint
  4. Dirty Page too much Checkpoint
Master Thread Checkpoint

在Master Thread中,会以每秒或者每10秒一次的频率,将部分脏页从内存中刷新到磁盘,这个过程是
异步的。正常的用户线程对数据的操作不会被阻塞。

FLUSH_LRU_LIST Checkpoint

FLUSH_LRU_LIST checkpoint是在单独的page cleaner线程中执行的。
MySQL对缓存的管理是通过buffer pool中的LRU列表实现的,LRU 空闲列表中要保留一定数量的
空闲页面,来保证buffer pool中有足够的空闲页面来相应外界对数据库的请求。
当这个空间页面数量不足的时候,发生FLUSH_LRU_LIST checkpoint。
空闲页的数量由innodb_lru_scan_depth参数表来控制的,因此在空闲列表页面数量少于配置的
值的时候,会发生checkpoint,剔除部分LRU列表尾端的页面。

Async/Sync Flush Checkpoint

Async/Sync Flush checkpoint是在单独的page cleaner线程中执行的。
Async/Sync Flush checkpoint 发生在重做日志不可用的时候,将buffer pool中的一部分脏页刷
新到磁盘中,在脏页写入磁盘之后,事物对应的重做日志也就可以释放了。
关于redo_log文件的的大小,可以通过 innodb_log_file_size 来配置。

对于是执行Async Flush checkpoint还是Sync Flush checkpoint,由checkpoint_age以及
async_water_mark和sync_water_mark来决定。

async_water_mark=75%*innodb_log_file_size
sync_water_mark=90%*innodb_log_file_size
  1. 当checkpoint_age<sync_water_mark的时候,无需执行Flush checkpoint。也就说,redo
    log剩余空间超过25%的时候,无需执行Async/Sync Flush checkpoint。
  2. 当async_water_mark<checkpoint_age<sync_water_mark的时候,执行Async Flush
    checkpoint,也就说,redo log剩余空间不足25%,但是大于10%的时候,执行Async Flush
    checkpoint,刷新到满足条件1
  3. 当checkpoint_age>sync_water_mark的时候,执行sync Flush checkpoint。也就说,redo
    log剩余空间不足10%的时候,执行Sync Flush checkpoint,刷新到满足条件1。

在mysql 5.6之后,不管是Async Flush checkpoint还是Sync Flush checkpoint,都不会阻
塞用户的查询进程。

由于磁盘是一种相对较慢的存储设备,内存与磁盘的交互是一个相对较慢的过程
由于innodb_log_file_size定义的是一个相对较大的值,正常情况下,由前面两种checkpoint刷新
脏页到磁盘,在前面两种checkpoint刷新脏页到磁盘之后,脏页对应的redo log空间随即释放,
一般不会发生Async/Sync Flush checkpoint。同时也要意识到,为了避免频繁低发生Async/Sync
Flush checkpoint,也应该将innodb_log_file_size配置的相对较大一些。

Dirty Page too much Checkpoint

Dirty Page too much Checkpoint是在Master Thread 线程中每秒一次的频率实现的。
Dirty Page too much 意味着buffer pool中的脏页过多,执行checkpoint脏页刷入磁盘,保证
buffer pool中有足够的可用页面。
Dirty Page 由innodb_max_dirty_pages_pct配置,innodb_max_dirty_pages_pct的默认值在
innodb 1.0之前是90%,之后是75%

重做日志落盘

InnoDB存储引擎会首先将重做日志信息先放入重做日志缓冲中,然后再按照一定频率将其刷新到
重做日志文件。重做日志缓冲一般不需要设置得很大,因为一般情况每一秒钟都会讲重做日志缓 冲刷新到日志文件中。可通过配置参数
innodb_log_buffer_size 控制,默认为8MB。

操作系统的文件系统是带有缓存的,当InnoDB向磁盘写入数据时,有可能只是写入到了文件系统的缓
存中,没有真正的“落袋为安”。
InnoDB的innodb_flush_log_at_trx_commit属性可以控制每次事务提交时InnoDB的行为。
当属性值为0时,事务提交时,不会对重做日志进行写入操作,而是等待主线程按时写入;
当属性值为1时,事务提交时,会将重做日志写入文件系统缓存,并且调用文件系统的fsync,将文
件系统缓冲中的数据真正写入磁盘存储,确保不会出现数据丢失;
当属性值为2时,事务提交时,也会将日志文件写入文件系统缓存,但是不会调用fsync,而是让文
件系统自己去判断何时将缓存写入磁盘。

innodb_flush_log_at_commit是InnoDB性能调优的一个基础参数,涉及InnoDB的写入效率和数
据安全。当参数值为0时,写入效率最高,但是数据安全最低;参数值为1时,写入效率最低,但
是数据安全最高;参数值为2时,二者都是中等水平。一般建议将该属性值设置为1,以获得较高
的数据安全性,而且也只有设置为1,才能保证事务的持久性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章