Skip to the content.

MySQL InnoDB存储引擎

记录 《MySQL InnoDB 存储引擎》读书过程中感觉重要的部分内容。

PS:非 DBA,故不会太细致,主要学习原理。

B/B+ Tree

B 树也称 B-树/平衡多路查找树。

B-Tree 定义如下:

因为 B 树的中间节点存储了数据,所以整个树的每一层都有可能查找到要查找的数据,查询性能不稳定,如:查询数据可能只要读一次磁盘块,可能要读 100 次磁盘块,数据量一大,平均 IO 次数就很大,不适合做索引。

B+Tree

B+Tree 应用场景

数据库索引就采用了 B+Tree。B+Tree 索引数据有序,能够进行范围查询,且 IO 次数少,一般千万级别的数据量最多也仅 3 次 I/O 即可找到数据。B+Tree 的结点一般会铺满一个磁盘块。

MySQL索引数据结构

InnoDB支持的几种常见的索引

数据结构演变

二分查找–> 二叉查找树 –> AVL 树 –> B-Tree –> B+Tree

B+Tree索引

分为聚集索引 (clustered index) 和辅助索引 (secondary index)

聚集索引和辅助索引的区别是,聚集索引叶子节点存放的是一整行的信息;而辅助索引叶子节点存放的是主键的值。

聚集索引

按照每张表的主键构造一棵 B+Tree。叶子节点存放的即为整张表的行记录数据。由于实际的数据页只能按照一颗 B+Tree 进行排序,因此每张表只能拥有一个聚集索引

聚集索引对于主键的排序查找和范围查找速度非常快。

辅助索引

叶子节点并不包含记录的全部数据。叶子节点中的索引行中还包含一个书签 (InnoDB 存储引擎的书签就是相应行数据的聚集索引键)

辅助索引不影响聚集索引。可以通过辅助索引,找到对应数据的指向主键索引的主键。然后通过主键索引来找到一个完整的行记录 (辅助索引存数据的主键,然后通过主键索引找完整记录??)

如:主键是 id,有 id,age,name 三个字段。如果查询用到了辅助索引。

select * from user where age = 18. 
# 通过辅助索引找到age=18对应的主键索引
# 然后通过主键索引找到完整的数据

在一棵高为 3 的辅助索引树种查找数据,需要对这棵辅助索引树遍历 3 次找到指定主键,如果聚集索引树的高度同样为 3,那么还需要对聚集索引进行 3 次查找,最终找到一个完整的行数据所在的页,一共需要 6 次逻辑 IO 访问以得到最终的一个数据页。

哈希算法

就是哈希表的那个。

InnoDB 存储引擎种的哈希算法。

常用的散列有:除法散列,乘法散列或全域散列。

MySQL体系结构和存储引擎

体系结构

存储引擎

InnoDB存储引擎

MyISAM存储引擎

Memory存储引擎

命令汇总

行锁和表锁

InnoDB存储引擎

概述

InnoDB体系架构

有多个内存块,内存块组成一个大地内存池。

有后台线程,主要负责刷新内存池中的数据。

后台线程

Master Thread

Master Thread是一个非常核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓冲 (INSERTBUFFER) 、UNDO 页的回收等。

IO Thread

在 InnoDB 存储引擎中大量使用了 AIO (Async IO) 来处理写 IO 请求,这样可以极大提高数据库的性能。而 IO Thread 的工作主要是负责这些 IO 请求的回调 (callback) 处理。

Purge Thread

事务被提交后,其所使用的 undolog 可能不再需要,因此需 Purge Thread 来回收已经使用并分配的 undo 页。在 InnoDB 1.1 版本之前,purge 操作仅在 InnoDB 存储引擎的 Master Thread 中完成。而从 InnoDB 1.1 版本开始,purge 操作可以独立到单独的线程中进行,以此来减轻 Master Thread 的工作,从而提高 CPU 的使用率以及提升存储引擎的性能。用户可以在 MySQL 数据库的配置文件中添加如下命令来启用独立的 Purge Thread:

[mysqld]
innodb_purge_thrreads = 1

Page Cleaner Thread

Page Cleaner Thread 是在 InnoDB 1.2.x 版本中引入的。其作用是将之前版本中脏页的刷新操作都放入到单独的线程中来完成。而其目的是为了减轻原 MasterThread 的工作及对于用户查询线程的阻塞,进一步提高 InnoDB 存储引擎的性能

内存

缓冲池

CPU 速度与磁盘速度之间差距过大,基于磁盘的数据库系统通常用缓冲池技术来提高数据库的整体性能。

重要内容提及

在数据库中读取页的操作:先将从磁盘读取到页放入缓冲池中,这个过程称为将页“FIX”在缓冲池。下一次读取时,先在缓冲池中找。 (与 OS 的页面查找类似)

对数据库中页的修改,先改缓冲池中的页,再以一定的频率刷新到磁盘上。以一种称之为 Checkpoint 的机制刷新回磁盘。

缓存池中缓存的数据页类型:索引页、数据页、插入缓冲、自适应哈希索引、InnoDB 存储的锁信息、数据字典信息等。不过缓存索引页和数据页占缓冲池很大的一部分~

从 InnoDB 1.0.x 开始,允许多个缓冲池实例

LRU

MySQL InnoDB 的 LRU 并非传统的 LRU,新数据是存在 midpoint 位置而非首部。

数据库中的缓冲池是通过 LRU (Latest Recent Used,最近最少使用) 算法来进行管理的。

MySQL InnoDB 的 LRU 并非传统的 LRU,新数据是存在 midpoint 位置。这个算法在 InnoDB 存储引擎下称为 midpoint insertion strategy。默认配置下在 LRU 列表长度的 5/8 处。midpoint 之后的列表称为 old 列表,之前的列表称为 new 列表。可简单理解为,midpoint 之前的都是最为活跃的热点数据。

当前数据可能只是这次要用到,如果直接把数据放到链表的首部,那么可能会让真正的热点数据丢失,因此引入了 midpoint 机制。

用户可以对 midpoint 的值进行调整,比如用户预估自己的热点数据高达 90%,则可以调整 midpoint 的值。

# 数据插入到链表尾部10%的位置
set global innodb_old_blocks_pct = 10 

Checkpoin技术

挖坑,后面填

InnoDB关键特性

概述

自适应哈希索引原理:

InnoDB 存储引擎会监控对表上二级索引的查找,如果发现某二级索引被频繁访问,二级索引成为热数据,建立哈希索引可以带来速度的提升,则:

1️⃣自适应 hash 索引功能被打开

mysql> show variables like '%ap%hash_index';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_adaptive_hash_index | ON    |
+----------------------------+-------+
1 row in set (0.01 sec)

2️⃣经常访问的二级索引数据会自动被生成到 hash 索引里面去(最近连续被访问三次的数据),自适应哈希索引通过缓冲池的 B+Tree 构造而来 (缓冲池就是内存区域中的数据) ,因此建立的速度很快。

3️⃣缺陷

4️⃣自适应哈希索引的控制