内存模型
buffer pool(2.5G)
缓冲池是内存占比最大的部分,用于存放各种数据的缓存。通过页的维度进行存储,每一页的大小一般设置为16K。
读取时优先读取缓存数据,如果没有再从磁盘加载到缓存。通过LRU进行缓存更新。
更新时也是先更新缓存数据,被更新后的缓存数据所在页称为【脏页】,通过后台线程进行同步到磁盘,称为【刷脏页】。通过show engine innodb status查看缓冲池总大小、空闲大小、脏页数量。
根据缓存的数据类型不同分为:
- 索引页:
- 数据页:
- undo页:
- 插入缓冲:
- 哈希索引:
- 锁信息:
- 数据字典:
log buffer(8M)
存放redolog,通过一定频率进行刷新到磁盘(1s级别)。
addition buffer(8M)
存放LRU信息、锁等信息。
线程模型
master thread
完成存储引擎的主要工作。
内部由4个循环组成,会根据数据库的运行状态在4个不同循环中切换。
- 主循环:
- 每1s执行内容:
- log buffer刷新到磁盘(包括未提交的事务)总是
- 合并插入缓冲可能
- 刷脏页(最多100页)可能
- 切换到后台循环(无用户行为->数据库空闲)可能
- 没10s执行内容:
- 刷脏页可能
- 合并插入缓冲总是
- 刷log buffer日志总是
- 删除无用undo页总是
- 刷新100个总是
- 生成checkpoint总是
- 每1s执行内容:
- 后台循环:
- 删除无用undo页总是
- 合并20个插入缓冲总是
- 跳回主循环(数据库非空闲)可能
- 跳到刷新循环可能
- 刷新循环:
- 不断刷脏页可能
- 暂停循环:
- 挂起!
上述流程中的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的区别在于:
- binlog是mysql层面日志,redolog是innodb层面的日志。
- binlog记录逻辑数据(执行的sql语句,记录类似某个事务的某个操这样的信息),redolog记录物理数据(数据页的内容,它记录着类似『更改页面x 的指定偏移量的数据为k』,也就是脏页)。
- binlog在事务提交前一次性写入,redolog在事务执行过程中逐句写入。
- binlog影响db性能(1%),redolog几乎不影响(redo log buffer)。
- binlog记录全量日志,redolog在脏页刷盘之后会被删除(本质上redolog是为了提高写操作性能而存在的)
- 事务提交过程:
- 计算sql更新前后的差值sql,更新buffer pool的undo数据页,记录redolog。
- 更新buffer pool的数据页+索引页,记录redolog。
- 提交事务时,更新redolog中的事务状态,记录redolog。
- 持久化redolog,保证返回用户成功前上面3步的redolog持久化完成。
- 如果事务提交后宕机,恢复时根据事务状态已提交+数据页进行数据恢复。
- 如果事务未提交宕机,恢复时根据事务状态未提交+undo页进行数据回滚(所以说undolog保证了未提交事务的ACID特性)。
关键特性
insert buffer
属于缓冲页类型之一。
主键(聚集)索引是顺序访问索引页,插入时性能很高。
辅助(非聚集)索引无法顺序访问索引页,插入时性能较低。(非唯一,否则要进行唯一校验就无法提升性能)
所以对于非聚集索引的插入或更新操作,不是每一次直接插入索引页,而是先判断插入的非聚集索引页是否在buffer pool中,如果在则直接插入,如果不在则先放在insert buffer中,后续通过一定的频率进行刷新(将线程模型)。
double write
用于刷脏页机制的优化。
adaptive hash index
数据根据表的索引信息以及实际查询记录判断是否启用自适应哈希,只用于等值查询不用于范围查询,基于B+树的结构进行创建性能损耗很少,带来至少2倍以上的的读写性能提升。