内存模型

buffer pool(2.5G)

缓冲池是内存占比最大的部分,用于存放各种数据的缓存。通过页的维度进行存储,每一页的大小一般设置为16K。
读取时优先读取缓存数据,如果没有再从磁盘加载到缓存。通过LRU进行缓存更新。
更新时也是先更新缓存数据,被更新后的缓存数据所在页称为【脏页】,通过后台线程进行同步到磁盘,称为【刷脏页】。通过show engine innodb status查看缓冲池总大小、空闲大小、脏页数量。
根据缓存的数据类型不同分为:

  • 索引页:
  • 数据页:
  • undo页:
  • 插入缓冲:
  • 哈希索引:
  • 锁信息:
  • 数据字典:

log buffer(8M)

存放redolog,通过一定频率进行刷新到磁盘(1s级别)。

addition buffer(8M)

存放LRU信息、锁等信息。

线程模型

master thread

完成存储引擎的主要工作。
内部由4个循环组成,会根据数据库的运行状态在4个不同循环中切换。

  1. 主循环:
    1. 每1s执行内容:
      1. log buffer刷新到磁盘(包括未提交的事务)总是
      2. 合并插入缓冲可能
      3. 刷脏页(最多100页)可能
      4. 切换到后台循环(无用户行为->数据库空闲)可能
    2. 没10s执行内容:
      1. 刷脏页可能
      2. 合并插入缓冲总是
      3. 刷log buffer日志总是
      4. 删除无用undo页总是
      5. 刷新100个总是
      6. 生成checkpoint总是
  2. 后台循环:
    1. 删除无用undo页总是
    2. 合并20个插入缓冲总是
    3. 跳回主循环(数据库非空闲)可能
    4. 跳到刷新循环可能
  3. 刷新循环:
    1. 不断刷脏页可能
  4. 暂停循环:
    1. 挂起!

上述流程中的100、20、10s、1s等数字都是硬编码,所以主线程存在的问题就是已经跟不上时代的发展:上游流量高,下游的SSD达不到瓶颈。

文件模型

参数文件mysql

记录mysql所有启动和运行过程中的运行参数,以kv值形式存在
可以通过show variables; 查看所有参数信息。

日志文件mysql

  • 错误日志:记录启动和运行过程中的错误信息,如果mysql启动失败就应该看这个文件。
  • 慢查询日志:记录运行过程中的慢sql,阈值可以通过参数中配置(3s)。
  • 查询日志:记录运行过程中的查询sql。
  • 二进制日志:记录运行过程中的变更sql,用于数据恢复和主从复制。

套接字文件&pid文件mysql

前者用于本地连接mysql
后者存储mysql进程的pid

表空间文件innodb

默认表空间文件ibdata1、10M。
存储数据、索引、插入缓冲。可以单表单独建立表空间文件,也可以多表共享一个表空间文件。

重做日志innodb

记录了innodb的事务日志,和binlog的区别在于:

  1. binlog是mysql层面日志,redolog是innodb层面的日志。
  2. binlog记录逻辑数据(执行的sql语句,记录类似某个事务的某个操这样的信息),redolog记录物理数据(数据页的内容,它记录着类似『更改页面x 的指定偏移量的数据为k』,也就是脏页)。
  3. binlog在事务提交前一次性写入,redolog在事务执行过程中逐句写入。
  4. binlog影响db性能(1%),redolog几乎不影响(redo log buffer)。
  5. binlog记录全量日志,redolog在脏页刷盘之后会被删除(本质上redolog是为了提高写操作性能而存在的)
  6. 事务提交过程:
    1. 计算sql更新前后的差值sql,更新buffer pool的undo数据页,记录redolog。
    2. 更新buffer pool的数据页+索引页,记录redolog。
    3. 提交事务时,更新redolog中的事务状态,记录redolog。
    4. 持久化redolog,保证返回用户成功前上面3步的redolog持久化完成。
    5. 如果事务提交后宕机,恢复时根据事务状态已提交+数据页进行数据恢复。
    6. 如果事务未提交宕机,恢复时根据事务状态未提交+undo页进行数据回滚(所以说undolog保证了未提交事务的ACID特性)。

关键特性

insert buffer

属于缓冲页类型之一。
主键(聚集)索引是顺序访问索引页,插入时性能很高。
辅助(非聚集)索引无法顺序访问索引页,插入时性能较低。(非唯一,否则要进行唯一校验就无法提升性能)
所以对于非聚集索引的插入或更新操作,不是每一次直接插入索引页,而是先判断插入的非聚集索引页是否在buffer pool中,如果在则直接插入,如果不在则先放在insert buffer中,后续通过一定的频率进行刷新(将线程模型)。

double write

用于刷脏页机制的优化。

adaptive hash index

数据根据表的索引信息以及实际查询记录判断是否启用自适应哈希,只用于等值查询不用于范围查询,基于B+树的结构进行创建性能损耗很少,带来至少2倍以上的的读写性能提升。