【Mysql-InnoDB 系列】InnoDB 架构
封面图片来自:mysql 官方文档,8.0 版本,InnoDB Architecture。
一 概述
如上图所示,mysql 的 InnoDB 存储引擎架构,包括了内存架构和磁盘架构两部分。其中,内存架构部分包括:缓冲池(Buffer Poll)、修改缓冲区(Change Buffer)、自适应 hash 索引(Adaptive Hash Index)、日志缓冲区(Log Buffer)。磁盘架构包括:表、索引、表空间、双写缓冲区(Doublewrite Buffer)、重做日志(Redo Log)、撤销日志(Undo Logs)。
本章将阐述 Mysql InnoDB 的架构中的组成部分,并在后续系列文章中详细描述各部分的细节。
二 内存架构
2.1 缓冲池(Buffer Poll)
缓冲池是 InnoDB 位于主存储器中的一片区域,用于缓存访问过的表和索引数据。缓冲池允许直接从内存处理频繁使用的数据,这加快了处理速度。在专用服务器上,通常高达 80%的物理内存会分配给缓冲池。
为了提高大容量读操作的效率,缓冲池被分割成一个个可以容纳多行的页(pages)。为了方便缓存管理,缓冲池被实现成页的链表结构;很少使用的数据会使用 LRU 算法的一种变体从缓存中淘汰。
了解如何利用缓冲池将频繁访问的数据保存在内存中,是 MySQL 调优的一个重要方面。
2.2 修改缓冲区
修改缓冲区是一个特殊的数据结构,用于缓存不在缓冲池中的那些二级索引页的变更。由 insert, update 或 delete 这些 dml 操作导致被缓存的变化,将在当这些页被其他读操作加载到缓冲池后合并。
2.3 自适应 hash 索引
自适应散列索引特性,使 InnoDB 在具有适当的负载组合和充足的缓冲池内存的系统上,执行得更像内存数据库,而不会牺牲事务特性或可靠性。自适应哈希索引特性通过变量: innodb_adaptive_hash_index 开启,或在服务启动时通过--skip-innodb-adaptive-hash-index 参数关闭。
根据观察到的搜索模式,hash 索引是使用索引 key 的前缀来创建的。前缀可以是任意长度,并且可能只有 B 树中的一些值出现在哈希索引中。哈希索引是根据需要为经常访问的索引页构建的。
2.4 日志缓冲
日志缓冲区是保存即将写入磁盘上日志文件的数据的内存区域。日志缓冲区大小由变量 innodb_log_buffer_size 定义。默认的大小是 16MB。日志缓冲区的内容定期刷新到磁盘。大的日志缓冲区能够在事务提交前无需写入 redo 日志数据到磁盘的情况下执行大事务。因此,如果你有更新、插入、删除很多行记录的事务,可以通过增加日志缓冲区的大小来减少磁盘 I/O。
innodb_flush_log_at_trx_commit 变量控制日志缓冲区的内容如果写入并刷新到磁盘。innodb_flush_log_at_timeout 变量控制日志刷新频率。
三 磁盘架构
3.1 表
1、创建 InnoDB 表:即我们常用的 create table t.... 会在 InnoDB 引擎内建表。
2、创建外表:有点类似 hive。创建外表(即在数据目录之外建表)有几种不同的原因,例如:空间管理、I/O 优化,或在具有特定性能或容量特征的存储设备上存放表,例如 InnoDB 支持下列方法来创建外表:
2-1 使用 DATA DIRECTORY 语句(指定数据目录)
2-2 使用 CREATE TABLE ... TABLESPACE 语法;
2-3 在外部通用表空间上建表
3、导入 InnoDB 表
4、移动或拷贝 InnoDB 表
5、将表从 MyISAM 转换为 InnoDB
6、InnoDB 中的自动增量处理
3.2 索引
包括:
1、聚簇索引和二级索引
2、InnoDB 索引的物理结构
3、排序索引生成
4、InnoDB 全文索引
3.3 表空间
InnoDB 中包含多种表空间,列举如下:
1、系统表空间(The System Tablespace)
2、File-Per-Table Tablespaces
3、通用表空间(General Tablespaces)
4、Undo 表空间(Undo Tablespaces)
5、临时表空间(Temporary Tablespaces)
6、Server 离线时移动表空间文件
7、禁用表空间路径验证
8、Linux 系统表空间分配优化
9、表空间 AUTOEXTEND_SIZE 参数设置
3.4 双写缓冲区
双写缓冲区(doublewrite buffer)是一个存储区域,InnoDB 在将页面写入 InnoDB 数据文件中的适当位置之前,会在其中写入从缓冲池中刷新的页面。如果在页面写入过程中存在操作系统、存储子系统或意外的 mysqld 进程退出,InnoDB 可以在崩溃恢复期间从双写缓冲区中找到页的完好副本。
尽管数据被写入两次,但双写缓冲区不需要两倍的 I/O 开销或两倍的 I/O 操作。数据通过一次 fsync()函数调用,在一个大的顺序块写入 doublewrite 缓冲区(除非innodb_flush_method
被设置为O_DIRECT_NO_FSYNC
)。
MySQL 8.0.20 版本之前,双写缓冲区存储空间归属于 InnoDB 的系统表空间。MySQL 8.0.20 开始,双写表空间存储区域放在了双写文件中。
3.5 重做日志
重做日志(redo log)是一种基于磁盘的数据结构,用于在崩溃恢复期间更正由不完整事务写入的数据。在正常的操作中,重做日志对 SQL 语句或低级 API 调用产生的更改表数据的请求进行编码。在意外关闭之前未完成数据文件更新的修改,将在初始化期间和接受连接之前自动重放。
默认情况下,重做日志在磁盘上的物理标识是名为ib_logfile0
和 ib_logfile1
的两个文件。MySQL 以循环方式写入重做日志文件。重做日志中的数据按照受影响的记录进行编码,这些数据统称为重做。重做日志的数据传递由不断增加的 LSN 值表示。
3.6 撤销日志
撤销日志(undo log)是与单个读写事务相关联的撤消日志记录的集合。撤消日志记录包含有关如何撤消事务对聚集索引记录的最新更改的信息。如果另一个事务需要将原始数据视为一致读取操作的一部分,则会从撤消日志记录中检索未修改的数据。撤消日志存在于撤消日志段中,而撤消日志段包含在回滚段中。回滚段驻留在 undo 表空间和全局临时表空间中。
驻留在全局临时表空间中的撤消日志,用于用户定义的临时表中修改数据的事务。这些撤消日志不是重做日志,因为崩溃恢复不需要它们。它们仅用于服务器运行时的回滚。这种类型的撤消日志通过避免重做日志 I/O 而提高了性能。
版权声明: 本文为 InfoQ 作者【程序员架构进阶】的原创文章。
原文链接:【http://xie.infoq.cn/article/48544a3041634ca9ce62eaff4】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论