Mysql-Innodb存储引擎体系架构

1.Mysql体系结构

为了更好的理解Mysql,我们需要对Mysql的体系结构有一个大致的了解,下面是Mysql体系结构图以及各部分说明.
Mysql-Innodb存储引擎体系架构_第1张图片

结构 说明
Connectors 不同语言中与SQL的交互
Management Services & Utilities 管理服务和工具组件,例如备份恢复、MySQL复制、集群等
Connection Pool 连接池组件,管理缓冲用户连接、用户名、密码、权限校验、线程处理等需要缓存的需求
SQL Interface SQL接口组件,接收用户的SQL命令,并且返回用户需要查询的结果
Parser 查询分析器组件,SQL命令传递到解析器的时候会被解析器验证和解析
Optimizer 优化器组件,对查询进行优化
Cache & Buffer 缓冲组件,查询缓存,如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据,MySQL 8被取消
Engine 插件式存储引擎,是MySQL中具体与文件打交道的子系统,是MySQL中最具特色的一个地方
File System 物理文件

存储引擎是基于表的,而不是数据库.

2 InnoDB体系架构

Mysql-Innodb存储引擎体系架构_第2张图片

2.1 后台线程

InnoDB存储引擎是多线程的,因此后台有多个后台线程负责不同的任务.

2.1.1 Master Thread

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

2.1.2 IO Thread

在InnoDB存储引擎中大量使用AIO来处理写IO请求,可以极大的提高数据库的性能.
IO Thread主要负责这些IO请求的回调处理,共有4种IO Thread:wirte,read,insert buffer,log IO Thread.

2.1.3 Purge Thread

事务被提交后,其所使用的undo log(回滚日志)可能不再需要,因此需要Purge Thread来回收已经使用并分配的undo页.

在 1.1版本之前,purge操作仅在InnoDB的Master Thread中完成.而从1.1开始,purge操作可以独立到单独的线程中进行.

2.1.4 Page Cleaner Thread

Page Cleaner Thread是在InnoDB 1.2版本中引入的,作用是将之前版本中脏页刷新的操作都放到单独的线程中来完成.

目的是为了减轻Master Thread的工作及用户查询线程的阻塞,进一步提高InnoDB存储引擎的性能.

2.2 内存

2.2.1 缓冲池

InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。由于CPU速度与磁盘速度之间的鸿沟,基于磁盘的系统通常使用缓存池技术来提供数据库的整体性能。

在数据库中进行读取页的操作,首先将从磁盘读到的页放在缓冲池中,这个过程称为将页“FIX”在缓冲池中。下一次再读相同的页时,首页判断该页是否在缓存池中。若在缓冲池中,称该页在缓冲池中被命中,直接读取该页。否则,读取磁盘上的页。

对于数据库中页的修改操作,首先修改在缓冲池中的页,然后再以一定的频率(checkpoint机制)刷新到磁盘上。

缓冲池的大小直接影响着数据库的整体性能。
通过命令show variables like 'innodb_buffer_pool_size'可以查看缓冲池的大小.
Mysql-Innodb存储引擎体系架构_第3张图片

从InnoDB 1.0.x版本开始允许有多个缓冲池实例,每个页根据哈希值平均分配到不同缓冲池实例中,增加并发处理能力.

2.2.2 LRU List,Free List 和 Flush List

页是InnoDB存储引擎磁盘管理的最小单位,每个页默认16KB;InnoDB存储引擎从1.2.x版本碍事,可以通过参数innodb_page_size将页的大小设置为4K、8K、16K。若设置完成,则所有表中页的大小都为innodb_page_size,不可以再次对其进行修改,除非通过mysqldump导入和导出操作来产生新的库。
可以理解为数据库的数据文件分配在磁盘空间上的逻辑划分?

LRU List(Latest Recent Used)
InnoDB中缓冲池是一个很大的内存区域,其中存放着各种类型的页.通常来说,数据库中的缓冲池是通过LRU(最近最少使用)算法进行管理的.最频繁使用的页在LRU列表的前端,最少使用的页在LRU列表的尾端.
在InnoDB中缓冲池页大小默认是16KB,同样使用LRU算法进行管理,只不过在InnoDB中对传统LRU算法进行了优化.在LRU列表中加入了midpoint(中点)位置,即新读取到的页并不直接放到LRU列表首部,而是放到了列表的midpoint位置,这个算法称为midpoint insertion strategy,默认配置下midpoint位置在LRU列表长度的5/8处,通过参数innodb_old_blocks_pct控制.
Mysql-Innodb存储引擎体系架构_第4张图片

通过命令看到默认值是37,表示新读取的也查到LRU列表尾端37%的位置.在InnoDB中把midpoint之后的列表称为old列表,之前的称为new列表.
同时InnoDB又引入参数innodb_old_blocks_time,表示页读取到midpoint位置后需要等待多久才会被加入到LRU列表的热端(new列表).
如果预估活跃的热点数据不止63%,可以通过sql语句来减少热点数据被刷出的概率.

SET GLOBAL innodb_old_blocks_pct=20;

通过表INNODB_BUFFER_PAGE_LRU来观察每个LRU列表中每个页的具体信息:

use information_schema;
SELECT TABLE_NAME,SPACE,PAGE_NUMBER,PAGE_TYPE FROM INNODB_BUFFER_PAGE_LRU;

Free List
当数据库刚启动时LRU列表是空的,没有任何页,这时的页都会放到Free列表中.当需要从缓冲池中分页时,首先从Free列表中查找是否有空闲页,如果有则将该页从Free列表中删除,放到LRU列表中.否则根据LRU算法淘汰LRU列表末尾页,将内存分配给新的页.
当页从LRU列表的old部分加入到new部分时,称此操作为page made young,因innodb_old_blocks_time设置而导致也没有从old移动到new的操作称为page not made young.可以通过命令来查看LRU列表和Free列表的使用和运行情况.

SHOW ENGINE INNODB STATUS

=====================================
2020-08-04 15:30:18 0x47f8 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 2 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 5 srv_active, 0 srv_shutdown, 25346 srv_idle
srv_master_thread log flush and writes: 25351
......
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137297920
Dictionary memory allocated 138904
Buffer pool size   8192
Free buffers       7718
Database pages     472
Old database pages 0
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 423, created 49, written 87
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 472, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
.....

可以看到Buffer pool size共有8192个页,及8192*16k的缓冲池.Free buffers表示当前Free列表中页的数量,Database pages表示LRU列表中页的数量.

Flush list
在LRU列表中的页被修改后,称该页为脏页,即缓冲池中的页和磁盘上的页的数据产生了不一致.这时会通过CHECKPOINT机制将脏页刷新回磁盘,而Flush列表中的页即为脏页列表.
在上面命令查看到的信息中,Modified db pages就显示了脏页的数量.

2.2.2 重做日志缓冲

Mysql默认情况下会有两个文件:ib_logfile0和ib_logfile1,这两个文件就是重做日志文件,或者事务日志.
重做日志的目的:万一实例或者介质失败,重做日志文件就能派上用场.
每个InnoDB存储引擎至少有一个重做日志文件组,每个文件组下至少有2个重做日志文件,如默认的ib_logfile0、ib_logfile1.InnoDB存储引擎先写重做日志文件1,当达到文件的最后时,会切换至重做日志文件2,当重做日志文件2也被写满时,会再被切换到重做日志文件1中.

InnoDB首先将重做日志信息放入这个缓冲区,然后按一定的频率将其刷新到重做日志文件.
重做日志缓冲一般不需要设置的很大,只需要保证每秒产生的事务量在这个缓冲大小之间即可.
通过innodb_log_buffer_size来控制,默认为8MB

SHOW VARIABLES LIKE 'innodb_log_buffer_size'

你可能感兴趣的:(InnoDB,MySql,mysql,数据库)