一、前言
MySQL 最早由瑞典 MySQL AB 公司开发,该公司由 Monty 在 1995 年创立;MySQL 这个名字来源于 Monty 的大女儿 My。它的成功不仅仅是因为免费,还有它的可靠性,稳定性和一些其它闪亮的特性。而 MySQL 中最核心的组建就是存储引擎,令人意外的是 Innodb 引擎的发展进程竟然比 MySQL 要早,甚至在时间上远远甩开了一些高级编程语言。
值得一提的是,MySQL 和 linux 两大开发源码的阵营都出自芬兰人之手,按照采访 Monty 时他的说法,芬兰人的本性就是固执和讨厌放弃,截止现在 Linus 在 Linux 方面坚持了 30 年,而 Monty 也坚持了 20 年,他们的这种专注和坚持是值得我们学习的。
理解 Innodb 的第一步就是要熟悉 show engine innodb shatus 中输出结果的含义,今天我们一起来学习它。
二、环境及输出
- 操作环境:MySQL 5.7.28
- 输出结果:
show engine innodb status\G
- 上面就是输出结果,主要包含一些 innodb 引擎中的一些状态,共有 10 个部分
BACKGROUND THREAD
:后台 Master 线程状态SEMAPHORES
:等待线程的列表及事件计数器,评估当前负载情况LATEST DETECTED DEADLOCK
:最新的几次死锁信息数据(只有发送死锁时显示)latest foreign key error
:最近几次外键错误信息(只有发生错误时显示)TRANSACTIONS
:innodb 事务统计信息FILE I/O
:显示的是I/O辅助线程的状态及性能计数器的状态INSERT BUFFER AND ADAPTIVE HASH INDEX
:insert buffer pool 和 AHI 状态LOG
:innodb 事务日志 Redo 的统计信息BUFFER POOL AND MEMORY
:innodb buffer pool 使用统计信息ROW OPERATIONS
:ROW 操作和其它统计信息
三、内容解析
show engine innodb status
显示的不是当前实时
的状态,而是过去某个时间范围
的状态,上图为输出的时间信息表示:查询信息为过去的 21 秒内,每两秒内平均值
介绍:Master 线程三种状态
- Master 线程是 innodb 引擎中最
重要
的线程,主要负责异步刷新数据
维护数据一致性
处理,有三种
工作状态,每次循环都会根据数据库
状态选择
其中一种工作状态。 Active
是 Master 线程判断系统处于忙碌状态
时选择的工作模式,它的循环数量增加主要与数据变化有关,与查询无关。Idle
是 Master 线程判断系统处于空闲状态
选择的工作模式,Idle 与 Active 两种工作模式做的事情几乎都一样,只不过执行时间间隔
不同。shutdown
是在关闭实例时才会选择的工作模式。
解析:输出解析
- 上图是一台比较
空闲
的实例
运行的结果,可以看到srv_active
为 567 而srv_idle
则为 1756519 远远大于 active 循环次数,所以可以对比两 active 和 idle 的值来判断
系统的负载
情况。 - 相对的如果实例输出的结果
srv_idle
远远大与active
则可以认为系统处于忙碌状态
。
- FILE I/O 主要是关于 innodb 中
IO Thread
线程的相关信息。 - IO Thread 线程分别为:
Read thread
、Write thread
、Insert buffer thread
、Log thread
使用的是异步
I/O 模型,处理不同类型的 I/O 请求和回调。 - 可以通过上图信息清晰看到 IO Thread 的信息,其中
read thread
和write thread
线程分别
有4
个,Log thread 和 insert buffer thread 线程分别各一个,其中 read 和 write 线程可以根据参数
来调整。
BUFFER POOL AND MEMORY
主要是关于 Innodb 的缓存池
管理相关数据
Total large memory allocated
:innodb 分配的总内存
(byte)Dictionary memory allocated
:innodb数据字典分配的内存数(byte)Buffer pool size
:缓冲池分配的页数Free buffers
:缓冲池空闲页数Database pages
:LRU 列表中分配的数据页
(LRU 是 innodb 管理缓存
的算法)Old database pages
:LRU 在old sublist
部分页的数量Modified db pages
:buffer pool 中的数据脏页
Pending reads
:挂起读的数量
LRU
算法介绍:数据库缓存
技术中都会使用的算法
- 算法思想:LRU 的
本质
是让数据页
在缓存中长时间保留
,提高查询访问效率
,但是缓存是有限
的,LRU 的作用就是减少
重复数据页加载频率
。 - 算法解析:LRU 是 innodb 中的一种
定制化算法
,首先它会有一个列表
,叫LRU LIST
上面存放一些数据页
,这个列表就是Database pages
上图是 6885 个数据页 大约 1MB innodb 在 LRU 列表中加入了参考点
,叫midpoint
当访问到的数据页不在缓冲区
会直接将磁盘中的数据页调到缓冲区队列;innodb 不是将数据页直接插入到缓冲区队列
的队头
,而是插入 LRU 列表的midpoint
位置。默认配置 midpoint 是在整个列表长度的5/8
处,和数学中的黄金分割 0.618 很接近,midpoint 是由innodb_old_blocks_pct
控制。LRU LIST
在 midpoint 之前的列表称为young sublist
或者sublist of new block
里面的数据是热数据,而LRU LIST
在midpoint
之后的列表称为old sublist
或者sublist of old block
。
- 算法过程:当
缓冲池
不能存放新读取
到的页时,将首先释放 LRU 列表中尾端
的页。当一些全表扫描如果进入sublist of new block
区域,整个 LRU 就会是性能瓶颈
,这种情况叫缓存污染
。为了解决这种问题,innodb 加入了innodb_old_blocks_time
来表示数据页读取到 mid 位置后需要等待
多久才会进入 LRU 列表的热端
,默认为1000 毫秒
,可以设置此参数保证热点数据
不会被轻易刷出。
Innodb 引擎日志
管理
- 上图主要展示的是关于 innodb
日志
相关,所以我们需要了解 innodb 引擎中日志的作用,主要有两种类型的日志redo log
重做日志和undo log
回滚日志,分别存储在 ib_logfile 和 ibdata 文件中。 - LSN 介绍:redo 日志的作用是为了维护事务的
持久性
和故障自动恢复
,都会基于 LSN 日志序列号,LSN 是一个一直递增的整型数字
(8 个字节),表示事务写入到日志的字节总量
,每个数据页和重做日志及checkpoint
都有 LSN。 checkpoint
:innodb 的刷盘
机制,可以将buffer poo
l 中的数据脏页
刷写到磁盘
。- redo 日志工作机制:上面已经提过 redo 日志主要维护事务的
持久化存储
,我们现在认识LSN
和checkpoint
后仔细讨论,当执行一条DML
语句时 innodb 会将硬盘中需要改动
的数据页加载到 buffer pool正常逻辑
是在内存
中修改完成后再刷到磁盘
中,但是这样有风险如果此时宕机
buffer pool 中没有刷写到到数据就会失效
,所以 innodb 会先将改动数据记录加载到redo buffer pool
中然后再由它快速刷写到redo 的物理存储空间
中,此时如果宕机那么原数据+改动数据记录
就可以恢复
到宕机前的状态
,这个恢复过程就是故障自动恢复
机制,MySQL 在启动时会对比数据和 ib_logfile 中到 LSN 编号,如果不一样则认为数据不一致
,启动自动故障恢复机制恢复数据后才会启动
成功。 - undo 日志工作机制:undo 日志主要
维护
的事务的原子性
,事务执行过程会将事务的反操作
记录到 undo物理空间
中,默认在ibdata
共享文件中,但是 ibdata 太过庞大5.7 版本
后可以通过innodb_undo_tablespaces
指定需要匹配几个 undo 文件。
LOG
数据解析:
Log sequence number
:LSN1 当前系统 LSN 最大值,新的事务日志将在原日志基础上生成(LSN1 + 新日志的大小)Log flushed up to
:LSN2 当前已经写入日志文件的 LSNPages flushed up to
:LSN3 当前最旧的数据脏页对应的 LSN 执行 checkpoint 时可以直接将此 LSN 写入到日志文件。Last checkpoint at
:LSN4 当前已经被 checkpoint 写入的 LSN
- 主要是
等待线程
的列表及事件计数器和一些锁
的情况,可以评估系统的负载情况
。 - 目前这部分相对来说用的比较少,网络上的资料比较模糊,详细描述后补。
- 死锁一般是
事务
相互等待
对方资源,最后形成环路
造成的。出现死锁 MySQL 也会检测到,然后通过回滚事务
解决。发生死锁会增加系统负担
,MySQL错误日志
也会记录死锁问题,查询到根源
然后解决和避免
死锁问题。当然也可以通过上图发现和结果最近的几次死锁问题。除了死锁系统还有外键错误记录。
三、总结
上面我们介绍 innodb 体系结构
中比较重要
的指标,从 show engine innodb shatus
的结果就可以看出 innodb 引擎的一个大体结构,四个线程、buffer pool、redo 和 undo、锁机制和相关特性,当然这只是冰山一角
,要想真正理解 innodb 还需要多花点时间
。