图解MySQL | [原理解析] MySQL insert 语句的磁盘写入之旅

做者及简介:
黄 炎,爱可生首席技术官;
王 悦,爱可生研发团队成员,负责数据库管理平台相关项目的开发和故障排查,好奇 MySQL 技术原理及各种数据库实现方案。
本文来源:转载自公众号-图解 MySQL
*爱可生开源社区出品,原创内容未经受权不得随意使用,转载请联系小编并注明来源。

一条 insert 语句在写入磁盘的过程当中到底涉及了哪些文件?顺序又是如何的?下面咱们用两张图和你们一块儿解析 insert 语句的磁盘写入之旅。数据库

图 1:事务提交前的日志文件写入

1.jpg

旅途过程:

  1. 首先 insert 进入 server 层后,会进行一些必要的检查,检查的过程当中并不会涉及到磁盘的写入。
  2. 检查没有问题以后,便进入引擎层开始正式的提交。咱们知道 InnoDB 会将数据页缓存至内存中的 buffer pool,因此 insert 语句到了这里并不须要马上将数据写入磁盘文件中,只须要修改 buffer pool 当中对应的数据页就能够了。
  • buffer pool 中的数据页刷盘并不须要在事务提交前完成,其中的交互过程咱们会在下一张图中分解。
  1. 但仅仅写入内存的 buffer pool 并不能保证数据的持久化,若是 MySQL 宕机重启了,须要保证 insert 的数据不会丢失。redo log 所以而生,当 innodb_flush_log_at_trx_commit=1 时,每次事务提交都会触发一次 redo log 刷盘。(redo log 是顺序写入,相比直接修改数据文件,redo 的磁盘写入效率更加高效)
  2. 若是开启了 binlog 日志,咱们还需将事务逻辑数据写入 binlog 文件,且为了保证复制安全,建议使用 sync_binlog=1 ,也就是每次事务提交时,都要将 binlog 日志的变动刷入磁盘。

综上(在 InnoDB buffer pool 足够大且上述的两个参数设置为双一时),insert 语句成功提交时,真正发生磁盘数据写入的,并非 MySQL 的数据文件,而是 redo log 和 binlog 文件。然而,InnoDB buffer pool 不可能无限大,redo log 也须要按期轮换,很难容下全部的数据,下面咱们就来看看 buffer pool 与磁盘数据文件的交互方式。缓存

名词背景说明

double write 背景

InnoDB buffer pool 一页脏页大小为 16 KB,若是只写了前 4KB 时发生宕机,那这个脏页就发生了写失败,会形成数据丢失。为了不这一问题,InnoDB 使用了 double write 机制(InnoDB 将 double write 的数据存于共享表空间中)。在写入数据文件以前,先将脏页写入 double write 中,固然这里的写入都是须要刷盘的。有人会问 redo log 不是也能恢复数据页吗?为何还须要 double write?这是由于 redo log 中记录的是页的偏移量,好比在页偏移量为 800 的地方写入数据 xxx,而若是页自己已经发生损坏,应用 redo log 也无济于事。安全

insert buffer 背景

InnoDB 的数据是根据汇集索引排列的,一般业务在插入数据时是按照主键递增的,因此插入汇集索引通常是顺序磁盘写入。可是不可能每张表都只有汇集索引,当存在非汇集索引时,对于非汇集索引的变动就可能不是顺序的,会拖慢总体的插入性能。为了解决这一问题,InnoDB 使用了 insert buffer 机制,将对于非汇集索引的变动先放入 insert buffer ,尽可能合并一些数据页后再写入实际的非汇集索引中去。性能

图 2:事务提交后的数据文件写入

2.jpg

旅途过程:

  1. 当 buffer pool 中的数据页达到必定量的脏页或 InnoDB 的 IO 压力较小 时,都会触发脏页的刷盘操做。
  2. 当开启 double write 时,InnoDB 刷脏页时首先会复制一份刷入 double write,在这个过程当中,因为double write的页是连续的,对磁盘的写入也是顺序操做,性能消耗不大。
  3. 不管是否通过 double write,脏页最终仍是须要刷入表空间的数据文件。刷入完成后才能释放 buffer pool 当中的空间。
  4. insert buffer 也是 buffer pool 中的一部分,当 buffer pool 空间不足须要交换出部分脏页时,有可能将 insert buffer 的数据页换出,刷入共享表空间中的 insert buffer 数据文件中。
  5. 当 innodb_stats_persistent=ON 时,SQL 语句所涉及到的 InnoDB 统计信息也会被刷盘到 innodb_table_stats 和 innodb_index_stats 这两张系统表中,这样就不用每次再实时计算了。
  6. 有一些状况下能够不通过 double write 直接刷盘spa

    • a. 关闭 double write
    • b. 不须要 double write 保障,如 drop table 等操做

汇总两张图,一条 insert 语句的全部涉及到的数据在磁盘上会依次写入 redo log,binlog,(double write,insert buffer) 共享表空间,最后在本身的用户表空间落定为安。日志

相关文章
相关标签/搜索