前言

深入了解一下 InnoDB

概念

数据库:物理数据库的文件及其他文件类型的集合。

mysql 线程数与cpu的关系 关于mysql线程独享内存_mysql 线程独享内存

实例:MySQL 数据库由后台线程以及一个共享内存区域组成。共享内存可以被运行的后台线程所共享。实例是用于操作数据库文件的。实例表示的是一个管理软件。

mysql 线程数与cpu的关系 关于mysql线程独享内存_mysql 线程数与cpu的关系_02

存储引擎

面向表的一种存储结构和算法实现。不同的存储引擎会有不同的特性,适应不同的场合。

InnoDB MySQL5.5 后的默认引擎。支持事务,表独立的 ibd 文件,支持 MVCC 来获得高并发性。存储方式为 聚集(clustered) 。

MyISAM 不支持事务,数据和索引文件分开存储,缓冲池只缓冲索引文件,支持全文索引。

MySQL 连接方式

TCP/IP 套接字 最常用

UNIX 域套接字 本机上使用

管道、共享内存 (比较少用)

OLTP 和 OLAP

OLTP:联机事务处理(on-line transaction processing)。主要是基本的,日常的事务处理,例如银行交易。强调数据库的内存效率,并发等,主要面向数据库。

OLAP:联机分析处理(On-Line Analytical Processing)。数据仓库的主要应用,支持复杂的分析操作,并提供直观易懂的查询效果。主要面向数据仓库,强调应用的磁盘IO,分区等功能。

InnoDB 体系

InnoDB 是实现 OLTP 应用的首选存储引擎。

InnoDB 存储引擎的体系架构

体系架构整体来说,简单可以分为文件,内存池和多个进程/线程。引擎的主要工作就是维护线程,并操作线程去刷新内存池的数据,保证内存池的缓存是最近的数据(性能),在异常情况下需要保证InnoDB能够恢复到正常运行状态(日志)。

实例 后台线程

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

2、IO Thread:InnoDB 存储引擎大量使用了 AIO 来处理IO请求,这样可以大大提高数据库的性能。IO Thread 主要是负责处理这些 IO 请求的回调处理。

// IO Thread 组默认有9个,1个insert buffer,1个log,4个read线程,4个write线程

I/O thread 0 state: waiting for completed aio requests (insert buffer thread)

I/O thread 1 state: waiting for completed aio requests (log thread)

I/O thread 2 state: waiting for completed aio requests (read thread)

I/O thread 3 state: waiting for completed aio requests (read thread)

I/O thread 4 state: waiting for completed aio requests (read thread)

I/O thread 5 state: waiting for completed aio requests (read thread)

I/O thread 6 state: waiting for completed aio requests (write thread)

I/O thread 7 state: waiting for completed aio requests (write thread)

I/O thread 8 state: waiting for completed aio requests (write thread)

I/O thread 9 state: waiting for completed aio requests (write thread)

复制代码3、Purge Thread 事务被提交后,所用的undolog不需要来,因此需要 Purge Thread 进行回收。线程的数量可以通过以下配置进行设定。这个原来是 Master Thread 的工作,这个设定是为了减轻 Master Thread 的工作。

[mysqld]

innodb_purge_threads=1

复制代码4、Page Cleaner Thread InnDB 1.2.x 引入的,用于把脏页的刷新操作写到磁盘中,本来是Master Thread做的,这个设定为了减轻Master Thread 的操作。

实例 内存

1、缓冲池

1.1 FIX 表示把磁盘的页数据读取到缓存中

1.2 命中 线程读取到缓存中的页数据

1.4 缓冲池包含以下数据

1.4.1 索引页 (大部分)

1.4.2 数据页 (大部分)

1.4.3 undo页

1.4.4 插入缓冲页

1.4.5 自适应哈希索引

1.4.6 锁信息 等等

InnoDB 存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。CPU 和 磁盘的速度鸿沟,就要靠缓冲池技术来提高数据库的整体性能。

2、LRU List、Free List 和 Flush List 对上面的缓冲池进行管理

一般来说,数据库的缓冲池是通过 LRU 算法进行管理的。最频繁使用的页在 LRU 的前端,最少使用的页在 LRU 的尾端。当缓冲池不能存放新读取到的页时,优先放弃 LRU 尾端的页数据。

InnoDB 对 LRU 做了一些优化,增加 midpoint,防止一些SQL大量加载数据时,对 LRU 队列直接刷新,导致热点数据快速缓存失效和加载。这个算法首先会把新数据写在midpoint的位置,而不是热端,等到这个数据等待一定时间后(innodb_old_blocks_time=1000)时,才会被写入热端。

Free List,控制空白页的数据结构。当数据库刚启动时,所有的缓存都是空的,那个所有的页信息都记录在 Free List 中。加载磁盘页数据时,假如空闲页存在,则直接选择空闲页写入,并注册到 LRU 列表中。否则走 LRU 淘汰。

Flush List,用于管理将页刷回磁盘的工作。这个和LRU List不一样,LRU List是管理页是否可用的。

3、redo log buffer

在内存部分,重做缓存日志 redo log buffer 是帮助实例快速写入 redo log 而设立的。一般会每 1s 刷新缓存到日志文件中。大小默认设置为 16M。MySQL 8

mysql> show variables like 'innodb_log_buffer_size'\G;

*************************** 1. row ***************************

Variable_name: innodb_log_buffer_size

Value: 16777216

1 row in set (0.00 sec)

复制代码

4、额外的内存池

在向缓冲池申请内存时,每个缓冲池中的帧缓存(frame buffer),还需要对应地申请缓冲控制对象(buffer control block),因此,申请了很大的 InnoDB 缓冲池时,需要合理配置额外内存池。