MySQL-- InnoDB存储引擎-磁盘结构(2-2)

307 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情

2. 数据字典 ( Data Dictionary )

  • 数据字典(InnoDB Data Dictionary)

    MySQL中,数据字典包括了: 表结构、数据库名或表名、字段的数据类型、视图、索引、表字段信息、MySQL版本信息、存储过程、触发器等内容.

    InnoDB数据字典由内部系统表组成,这些表包含用于查找表、索引和表字段等对象的元数据。元数据物理上位于InnoDB系统表空间中。在MySQL8.0之前 由于历史原因,数据字典元数据在一定程度上与InnoDB表元数据文件(.frm文件)中存储的信息重叠。

image.png

注: MySQL8.0版本以后 将所有原先存放于数据字典文件中的信息,全部存放到数据库系统表中,即将之前版本的 .frm,.opt等文件都移除了,不再通过文件的方式存储数据字典信息

3. 双写缓冲区 ( Doublewrite Buffer Files)

  • 什么是写失效 ( 部分页失效 )

InnoDB的页和操作系统的页大小不一致,InnoDB页大小一般为16K,操作系统页大小为4K,InnoDB的页写入到磁盘时,一个页需要分4次写。

如果存储引擎正在写入页的数据到磁盘时发生了宕机,可能出现页只写了一部分的情况,比如只写了4K,就宕机了,这种情况叫做部分写失效(partial page write),可能会导致数据丢失。

image.png

  • 双写缓冲区 Doublewrite Buffer

    为了解决写失效问题,InnoDB实现了double write buffer Files, 它位于系统表空间,是一个存储区域。

    在BufferPool的page页刷新到磁盘真正的位置前,会先将数据存在Doublewrite 缓冲区。这样在宕机重启时,如果出现数据页损坏,那么在应用redo log之前,需要通过该页的副本来还原该页,然后再进行redo log重做,double write实现了InnoDB引擎数据页的可靠性.

    默认情况下启用双写缓冲区,如果要禁用Doublewrite 缓冲区,可以将innodb_doublewrite设置为0。

    mysql> show variables like '%innodb_doublewrite%';
    +--------------------+-------+
    | Variable_name      | Value |
    +--------------------+-------+
    | innodb_doublewrite | ON    |
    +--------------------+-------+
    1 row in set (0.01 sec)
    
  • 数据双写流程 image.png

    • step1:当进行缓冲池中的脏页刷新到磁盘的操作时,并不会直接写磁盘,每次脏页刷新必须要先写double write .
    • step2:通过memcpy函数将脏页复制到内存中的double write buffer .
    • step3: double write buffer再分两次、每次1MB, 顺序写入共享表空间的物理磁盘上, 第一次写.
    • step4: 在完成double write页的写入后,再将double wirite buffer中的页写入各个表的独立表空间文件中(数据文件 .ibd), 第二次写
  • 为什么写两次 ?

因为共享表空间是在ibdbata文件中划出2M连续的空间,专门给double write刷脏页用的, 由于在这个过程中,double write页的存储是连续的,因此写入磁盘为顺序写,性能很高;完成double write后,再将脏页写入实际的各个表空间文件,这时写入就是离散的了.

  • Change Buffer

    系统表空间中的change buffer是内存缓冲池中change buffer的备份,也就是说被持久化到了系统表空间中。在崩溃恢复的时候会从系统表空间的change buffer中读取信息到buffer pool。