引擎架构
引擎架构
整体架构图

In-Memory Structure
内存结构
Buffer Pool 缓冲池
缓冲池是主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频率刷新到磁盘,从而减小磁盘 IO,加快处理速度。
缓冲池以Page页为单位,底层采用链表数据结构管理 Page。根据状态,将 Page 分为三种类型:
- free page:空闲 page,未被使用
- clean page:被使用 page,数据没有被修改过
- dirty page:脏页,被使用 page,数据被修改过,其中数据与磁盘的数据产生了不一致
Change Buffer
8.0 以后引入的,之前版本是 insert buffer
主要针对非唯一的二级索引
Change Buffer:更改缓冲区(针对于非唯一二级索引页),在执行 DML 语句时,如果这些数据 Page 没有在 Buffer Pool 中,不会直接操作磁盘,而会将数据变更存在更改缓冲区 Change Buffer 中,在未来数据被读取时,再将数据合并恢复到 Buffer Pool 中,再将合并后的数据刷新到磁盘中。
与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。同样,删除和更新可能会影响索引树中不相邻的二级索引页,如果每一次都操作磁盘,会造成大量的磁盘 IO。有了 ChangeBuffer 之后,我们可以在缓冲池中进行合并处理,减少磁盘 IO。
Adaptive Hash Index
自动优化产生 hash 索引,提高效率
参数
adaptive_hash_index
: 控制是否开启自适应哈希索引
Log Buffer
存储包括如下两种 log:
redo log
undo log
参数
innodb_log_buffer_size
: 缓冲区大小,默认 16MBInnodb_flush_log_at_trx_commit
: 日志刷新到磁盘的时机- 1: 每次事务提交时,写入并刷新到磁盘
- 0: 没秒将日志写入并刷新到磁盘一次
- 2: 日志在每次提及后写入,并每秒刷新到磁盘一次
如果 MySQL 是一台单独的服务器,一般 80%的内存都会给 MySQL 的缓冲区
On-Disk Structure
磁盘结构
System Tablespace
系统表空间
innodb_data_file_path
:
File-Per-Table Tablespaces
独立表空间,即每个表的表空间
innodb_file_per_path
:
General Tablespaces
通用表空间
默认没有,可以通过create tablespace
来创建。
在创建表时,可以指定该表空间create table xxx tablespaces xx
。
Undo Tablespaces
撤销表空间
Temporary Tablespaces
临时表空间
Doublewrite Buffer Files
双写缓冲区
Doublewrite Buffer Files:双写缓冲区,innoDB 引擎将数据页从 Buffer Pool 刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据。
Redo Log
重做日志
两个文件,循环写入,来覆盖事务提交后无用的 redo log
后台线程
Matser Thread
作用:
- 脏页刷新
- 合并 insert buffer
- undo page clean
IO Thread
MySQL 有很多后台线程,其中包括了负责 IO 的相关线程 IO THREAD
- 参数 innodb_write_io_threads 写线程 默认四个,负责数据块的写入
- 参数 innodb_read_io_threads 读线程 默认四个,负责数据块的读取
- insert buffer thread
- redo-log thread
上面两个参数高并发下,可以设置为 8.
Purge Thread
作用: 真正的删除记录和删除 undo log
- 清理删除后的数据页的空间(因为之前的删除只是打上删除标签,并没有正真删除),
- 清理 undo log
举例:表 tb1 中有记录 pk=1,2,3; 此时 delete from tb1 where pk=1;
- pk=1 的记录标记为删除(delete-mark,info bits),数据库中 pk=1 的记录此时还是存在的,空间并没有被释放,该操作为同步操作(SQL 执行完,也就标记完成了)。
- purge ,该部分为后台线程(purge 线程)异步操作,会真正的删除该记录,且空间被释放。purge 线程是系统自动的,无法人工控制。
标记为已删除的原因:
- 该事物可能需要回滚,先作保留。
- 当事物 1 去删除 pk=1 且没有提交时, 事物 2 应该要能看到 pk=1 的记录(事物的隔离性)。