21-4-26_innodb内幕
一、第1章 MySQL体系结构和存储引擎
1.1 定义数据库和实例
数据库:
物理操作系统文件或者起形式文件类型的集合。
可以是frm、MYD、ibd等文件,或者内存之中的文件。
实例:
后台线程以及一个共享内存区组成,数据库实例才是真正操纵数据库文件。
单机情况:
数据库 < -- > 实例
一 一对应
集群情况:
可能存在一个数据库被多个实例使用。
MySQL:
单进程多线程架构。
读取配置文件:
以读取到的最后一个配置文件为准
查看顺序:
- linux:mysql --help | grep my.cnf
- windows:mysql --help
1.2 MySQL体系结构

- 连接池组件
- 管理服务和工具组件
- SQL接口组件
- 查询分析器组件
- 优化器组件
- 缓冲组件
- 插件式存储引擎:区别于其他数据库
- 物理文件
存储引擎基于表而不是数据库。
1.3 MySQL存储引擎
1.3.1 InnoDB存储引擎
-
支持事务、行锁、外键
-
MySQL5.5.8默认存储引擎
-
将数据放在逻辑的表空间
-
MVVC(多版本并发控制)来获得高并发性,四种隔离级别,默认
repeatable read可重复读,next-key locking来避免幻读,插入缓冲、二次写、自适应哈希索引、预读 -
聚集索引,每张表的存储都是按主键的顺序进行存放,没有显示指定主键则有
6字节的rowid作为主键
1.3.2 MyISAM存储引擎
- 不支持事务
- 表锁
- 全文索引
- 缓冲池只缓存索引文件
- 存储引擎表由MYD和MYI组成
- MYD存储数据文件
- MYI存放索引文件
- 只缓存索引文件,数据文件交由操作系统本身
1.3.3 NDB存储引擎
- 集群存储引擎
- 数据全部放在内存中(5.1版本可将索引数据放在磁盘上),主键查找速度快
- 连接操作(JOIN)在数据库层完成,而不是在存储引擎层,网络开销大,查询速度慢
1.3.4 Memory存储引擎
- 之前称 HEAP引擎
- 表中数据在内存中,数据库重启或崩溃,数据消失
- 适用临时存储数据的临时表
- 哈希索引
- 表锁
- 并发性能差
- 不支持TEXT和BOLB类型
1.3.5 Archive存储引擎
- Insert、select操作
- 压缩后存储,1:10
- 适合存储归档数据:日志
- 行锁,告诉的插入和压缩
1.4 各种存储引擎对比

查看存储引擎:
show engines \G
1.5 连接MySQL
1.5.1 TCP/IP
在任何平台都提供的连接方式,也是使用得最多的一种方式。
在通过TCP/IP 连接到MySQL实例时,数据库会先检查一张权限视图,用来判断发起请求的客户端IP是否允许连接到数据库实例。
1.5.2 命名管道和共享内存
配置文件中配置:
-
命名管道:
--enable-names-pipe -
共享内存:
--shared-memory- 客户端需要使用
--protocl=memory
- 客户端需要使用
1.5.3 UNIX域套接字
- linux、unix环境下
- 配置文件:
-socket=/tmp/mysql.sock - unix域套接字文件查找:
show variables like 'socket';
第2章 InnoDB存储引擎
2.3 InnoDB体系架构

InnoDB存储引擎有多个内存块,可认为组成了内存池,负责:
- 维护所有进程/线程需要访问的多个内部数据结构
- 缓存磁盘数据,方便快速读取,同时把内存中的缓存写入磁盘数据
- redo日志缓冲
后台线程主要是刷新内存池的数据,保证缓冲池中的内存是最新数据;同时将已修改文件刷新到磁盘;保证数据库发生异常下InnoDB能恢复到正常运行状态
2.3.1 后台线程
InnoDB存储引擎是多线程模型,后台有多个不同的后台线程
1、Master Thread
- 核心
- 将缓冲池的数据异步刷新到磁盘
- 脏页
- 合并插入缓冲
- undo页的回收
2、IO Thread
- 负责AIO来处理写IO请求的回调处理
mysql> show variables like 'innodb_version' ;
+----------------+--------+
| Variable_name | Value |
+----------------+--------+
| innodb_version | 8.0.19 |
+----------------+--------+
1 row in set, 1 warning (0.00 sec)
mysql> show variables like 'innodb_%io_threads'\G
*************************** 1. row ***************************
Variable_name: innodb_read_io_threads
Value: 4
*************************** 2. row ***************************
Variable_name: innodb_write_io_threads
Value: 4
2 rows in set, 1 warning (0.00 sec)
innodb_read_io_threads与innodb_write_io_threads设置读写IO Thread线程个数
mysql> show engine innodb status \G
I/O thread 0 state: wait Windows aio (insert buffer thread)
I/O thread 1 state: wait Windows aio (log thread)
I/O thread 2 state: wait Windows aio (read thread)
I/O thread 3 state: wait Windows aio (read thread)
I/O thread 4 state: wait Windows aio (read thread)
I/O thread 5 state: wait Windows aio (read thread)
I/O thread 6 state: wait Windows aio (write thread)
I/O thread 7 state: wait Windows aio (write thread)
I/O thread 8 state: wait Windows aio (write thread)
I/O thread 9 state: wait Windows aio (write thread)
IO 0 Thread是insert buffer thread
IO 1 Thread是log thread
其他是上述两个参数进行设置,且读线程的ID小于写线程
3、Purge Thread
事务提交后,Purge Thread来回收可能不再需要的undo日志
mysql> select version()\G
*************************** 1. row ***************************
version(): 8.0.19
1 row in set (0.06 sec)
mysql> show variables like 'innodb_purge_threads' \G
*************************** 1. row ***************************
Variable_name: innodb_purge_threads
Value: 4
1 row in set, 1 warning (0.00 sec)
4、Page Cleaner Thread
将之前版本中的脏页的刷新操作都放入到单独的线程中来完成,为了减轻Master Thread的工作及对于用户查询线程的阻塞,提高性能
2.3.2 内存
1、缓冲池
读取页时,将从磁盘的页放到缓冲池中(FLX),下一次再读相同的页时先进行判断,若在缓冲池中则称该页被命中,直接读取,否则在磁盘上读取
页操作,修改缓冲池中的页,再一定频率刷入磁盘,通过CheckPoint机制刷新

缓冲池中有:索引页,数据页,undo页,插入缓冲,自适应哈希索引,InnoDB存储的锁信息,数据字典信息
缓冲池实例数
mysql> show variables like 'innodb_buffer_pool_instances'\G
*************************** 1. row ***************************
Variable_name: innodb_buffer_pool_instances
Value: 1
1 row in set, 1 warning (0.00 sec)
将innodb_buffer_pool_instances设置大于1则可以得到多个实例
可以通过informeation_schema的表innod_buffer_pool_stats来观察缓冲池状态
mysql> select pool_id, pool_size,free_buffers, database_pages from innodb_buffer_pool_stats;
+---------+-----------+--------------+----------------+
| pool_id | pool_size | free_buffers | database_pages |
+---------+-----------+--------------+----------------+
| 0 | 8192 | 6971 | 1212 |
+---------+-----------+--------------+----------------+
1 row in set (0.00 sec)
2、LRU List、Free List和Flush List
LRU:最近最少使用算法
最频繁使用的页在LRU列表前端,最少使用的页在LRU列表的尾端, 当缓冲池不能存放新读取的页,将首选LRU列表尾端的页
缓冲池中页默认大小是16KB
midpoint位置,最新读取的页放在此位置,此算法称midpoint insertion strategy
mysql> show variables like 'innodb_old_blocks_pct'
-> ;
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_old_blocks_pct | 37 |
+-----------------------+-------+
1 row in set, 1 warning (0.00 sec)
占比37%,由innodb_old_blocks_pc控制
midponit之前的页称为new列表,热度高,之后的称old列表
不采用的话全表扫描时可能会将经常使用的页淘汰
innodb_old_blocks_time来管理,表示页读取到mid位置需要等待多久才会被移到前端,表示在这时间内多次访问一个页不需要将其放在new区域
Free列表:
服务器启动时LRU列表为空,页都在Free列表中。
当需要从缓冲池中分页时,首先从Free列表查找是否有空闲页,有则从Free列表移除,放入LRU列表中,否则淘汰LRU列表末尾的页,将该内存空间分配给新的页
当页从old移到new部分时,称page made young
因为innodb_old_blocks_time的设置导致没有从old到new则称page not made young
压缩页功能会将16KB的页压缩至1KB、2KB、4KB、8KB,此时由unzip_LRU列表进行管理
LRU列表包含unzip_LRU列表的数量
unzip_LRU列表分配:
在列表中对不同压缩页大小进行分别管理,其次通过算法进行内存的分配
例如对需要从缓冲池中申请4KB的页:
- 检查4KB的unzip_LRU列表,检查检查是否有空闲页
- 若有直接使用
- 否则,检查8KB的unzip_LRU列表
- 若能得到空闲页,则将此页分成2个4KB的页,放入4KB的unzip_LRU列表
- 若不能,从LRU列表申请一个16KB的空闲页,分成1个8KB的页,2个4KB的页,分别放入对应的列表

LRU列表中的页被修改后,成为脏页,即缓冲池的页和磁盘上的页的数据不一致,数据库会通过checkoint机制将脏页刷回磁盘,Flush列表中的页即为脏页列表,脏页既存在LRU列表,也存在于Flush列表中。
LRU列表管理缓冲池页的可用性,Flush列表来管理将页刷新到磁盘,互不影响。

3、redo日志缓冲
InnoDB将redo日志先放入重做日志缓冲(redo log buffer),然后按一定的频率将其刷新到redo日志文件。
innodb_log_buffer_size控制缓冲大小
mysql> show variables like 'innodb_log_buffer_size'
-> ;
+------------------------+----------+
| Variable_name | Value |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
1 row in set, 1 warning (0.00 sec)
redo日志刷新到磁盘的情况:
Master Thread将redo日志缓冲刷新到redo日志文件- 事务提交会刷新到redo文件
- 当redo日志缓冲池空间小于
1 / 2
4、额外的内存池
innodb对内存的管理是通过内存堆进行的
对一些数据结构本身的内存进行分配时,需要从额外的内存池进行申请,如缓冲池的帧缓冲、对应的缓冲控制对象(记录LRU、锁、等待信息),这些需要从额外的内存池进行申请
当额外的内存池空间不够时则向缓冲池进行申请
浙公网安备 33010602011771号