InnoDB存储引擎内存模型与磁盘同步

本文详细解析了InnoDB存储引擎的内存与磁盘交互机制,包括预读策略(线性预读和随机预读)、数据同步方法(脏页处理和异步刷脏),以及如何通过RedoLog保证数据一致性。重点讨论了为何选择RedoLog而非实时同步,并介绍了不同同步方案的优缺点。
摘要由CSDN通过智能技术生成

InnoDB存储引擎内存模型与磁盘同步

InnoDB数据结构如下:
在这里插入图片描述

1. 内存与磁盘数据交互机制

innoDB在内存跟磁盘之间是以page页为单位来交互的,因为如果用行交互,那么假如我查询n条数据,需要跟磁盘交互n次,但是page页可能会很少,也不会用extent区来交互,因为一个extent包含64个页,加载64个页到内存,会导致内存浪费。所以,基于内存的利用率与性能考虑,InnoDB选择了page页

2. 预读机制

预先把在查询过程中使用到的数据读到内存中,减少磁盘 I/O 操作。通过顺序预读,InnoDB 存储引擎可以利用自然的数据存储顺序,提高顺序扫描的效率,进而提高查询性能。

  • 线性预读:
    按照访问顺序的页来执行预加载 某个区里面的页面有多少个页按顺序访问了,那么就会预加载这个区里面所有的页。
    具体多少个页被顺序访问,具体配置为innodb_read_ahead_threshold
   -- 默认为56 可以配置0-64,因为一个extent为64个页
   SELECT @@innodb_read_ahead_threshold; 
  • 随机预读:
    根据缓存池中已有的页来预加载,如果在缓冲池中找到了来自同一个区连续的13个页面,InnoDB会异步发出一个请求来预取该区剩余的页面。
    通过开关开关控制,默认关闭:
   SELECT @@innodb_random_read_ahead;

3. 数据同步机制

为了提高效率,innodb每次更改数据,会去先判断内存是否存在,如果数据所在的page页存在内存,会直接更改内存中page的数据。那么在我们的系统中,就有2份数据,一份在内存,一份在磁盘,所以就需要数据同步,保证一致性。

  • 脏页
    这个在内存中改动过的、还没有同步到磁盘的页就是脏页。InnoDB的bufferpool中,将脏页信息单独放在一个链表,刷脏的时候,只需要从这个链表找就可以了,这个链表就叫做Flush链表。
  • 异步刷脏
    那么这些脏页怎么同步到磁盘的?是不是每次更改一条数据,我就把这个数据的page页同步到磁盘?假如每次操作都需要先跟磁盘同步,我们发现有以下几个问题:
    1. 由于内存跟磁盘交互的最小单位是page页,那么你改动一行数据,整个页都需要跟磁盘进行交互同步。
    2. 这个更改的数据你是不知道在哪个磁盘位置的,属于一个随机IO。如果每次都先保证同步到磁盘,那么操作数据会非常非常非常慢。
      所以,采用的是异步刷盘机制。
      刷脏是由异步线程去做的,具体的线程数由配置innodb_page_cleaners控制
      SELECT @@innodb_page_cleaners; -- 默认是4 但是不能超过buffer-pool的实例数
      SELECT @@innodb_buffer_pool_instances;

并且通过以下2个参数来控制我内存中的脏页量

     SELECT @@innodb_max_dirty_pages_pct_lwm; -- 当脏页数量低于特定阈值时InnoDB存储引擎开始刷新脏页的行为,默认10
     SELECT @@innodb_max_dirty_pages_pct; -- 内存中可以存在的脏页的最大百分比
  • 双写缓存区
    page页会异步刷新到磁盘,但是page页的大小是16k,而操作系统 的是4K,一个页是需要多次同步到磁盘的,中间如果出现操作系统,磁盘或者进程意外退出怎么办?
    所以Mysql提供了一个doubleWrite机制,就是page页刷新到磁盘的时候,把这个page数据写到不同的地方去,当出现问题时,由备份来达到持久性跟数据的一致性。

4. RedoLog

数据是异步刷新到磁盘的,那么假如,在同步到磁盘之前就宕机了。数据就丢失了,那么InnoDB怎么去保证数据的一致性与持久性呢?所以又引入了RedoLog日志。RedoLog又称作重做日志,当我发生异常情况,导致数据丢失的时候,我可以从我的RedoLog日志中找到我想要的数据。
Redolog记录的大概结构:
在这里插入图片描述
type:操作类型 插入、修改还是删除
spaceId:表空间ID
page numbwe: 所在的页
data: 修改的前后数据

RedoLog的目的,是去保证我的数据页在内存,但是还没有同步到磁盘的时候,宕机导致的数据丢失。所以在sql语句提交之前,肯定会保存改动的Redolog到redolog file文件。当改动数据还在内存,没有同步到磁盘就宕机的时候,会通过RedoLog文件里面找到改动点,进行同步到磁盘。RedoLogFile的大小是固定的,写入的日志数量是有限制的,并且它的目的只是去保证数据不丢失,数据落盘了,这些日志就没有用了,所以RedoLog采用的是循环覆盖写的方式。当RedoLog空间的大小满了的时候,会对以前数据进行覆盖。为了保证被覆盖的数据不会丢失,在Redolog快满的时候,也会去进行刷脏,刷脏后,对应的Redolog日志就无效可以被覆盖,所以RedoLog的写是循环写的方式。

为啥不直接实时数据同步到磁盘,而是要写入一个RedoLog文件呢?

1.因为bufferPool跟磁盘交互的最小单位是page,所以,只要page里面改动一条数据,整个page都会进行跟磁盘同步,导致不必要的同步。RedoLog只会同步某些记录。
2.你改动的数据是随机的,不是顺序的,随机IO的性能比较慢,但是RedoLog是一直往上加,是顺序IO,速度比数据page同步要快。

为了保证数据一致性跟持久性的同时,性能得到保证,innodb内存中又申请了一个LogBuffer区间,这个内存区间用来缓存我们的RedoLog, RedoLog不马上写到磁盘,而是先写LogBuffer,然后再从Log Buffer同步到磁盘。

RedoLog同步方案:

SELECT @@innodb_flush_log_at_trx_commit; //RedoLog同步方案默认设置为1

1: 每次事务提交时,将日志刷新到磁盘,安全性高,能够保证持久性,默认配置
0: 每秒从内存写到操作系统,并且刷新(fsync())到硬盘,可能会导致数据丢失
2:每次写入logbuffer 并且写到操作系统,但是每秒fsync()到磁盘,最终刷新交给操作系统操作,只要操作系统不挂,也能保证持久性,但是操作系统挂了,数据没刷新就会数据丢失
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值