【八股消消乐】MySQL存储引擎InnoDB知识点汇总
😊你好,我是小航,一个正在变秃、变强的文艺倾年。
🔔本专栏《八股消消乐》旨在记录个人所背的八股文,包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法
等相关知识点,期待与你一同探索、学习、进步,一起卷起来叭!
目录
- 题目
- 答案
- InnoDB 体系架构
- InnoDB 逻辑存储结构
- redo log 工作原理
题目
💬技术栈:MySQL
🔍简历内容:熟悉InnoDB体系架构、逻辑存储结构以及redo log工作原理。
🚩面试问:InnoDB 存储引擎的实现和运行原理是什么?
💡建议暂停思考10s,你有答案了嘛?如果你有不同题解,欢迎评论区留言、打卡。
答案
InnoDB 体系架构
(1)内存池
- 客户端读取数据时,如果数据存在于缓冲池中,客户端就会直接读取缓冲池中的数据,否则再去磁盘中读取;
- 对于数据库中的修改数据,首先是
修改在缓冲池中的数据
,然后再通过 Master Thread 线程刷新到磁盘上
。 - 缓冲池中
不仅缓存索引页和数据页
,还包括了undo 页,插入缓存、自适应哈希索引以及 InnoDB 的锁信息
等等。 - InnoDB 存储引擎会
先将重做日志信息放入到缓冲区中
,然后再刷新到重做日志文件中
。 - InnoDB 允许多个缓冲池实例,从而减少数据库内部资源的竞争,增强数据库的并发处理能力。
(2)后台线程
- Master Thread:主要负责
将缓冲池中的数据异步刷新到磁盘
中,除此之外还包括插入缓存、undo 页的回收等。 - IO Thread:负责读写 IO 的线程。
- Purge Thread:主要用于回收
事务已经提交了的 undo log
。 - Pager Cleaner Thread:新引入的一个用于
协助 Master Thread 刷新脏页到磁盘的线程
,它可以减轻 Master Thread 的工作压力,减少阻塞。
(3)存储文件
- .frm 文件:MySQL 中建立一张表都会生成一个.frm 文件,
用来保存每个表的元数据信息
的,主要包含表结构定义。 - .ibd 文件(独占表空间文件):
InnoDB 逻辑存储结构
InnoDB 逻辑存储结构分为表空间(Tablespace)、段 (Segment)、区 (Extent)、页 Page) 以及行 (row)。
(1)表空间(Tablespace):InnoDB 提供了两种表空间存储数据的方式,一种是共享表空间,一种是独占表空间
。
- InnoDB
默认会将其所有的表数据存储在一个共享表空间
中,即 ibdata1。 - 通过设置
innodb_file_per_table 参数为 1(1 代表独占方式)
开启独占表空间模式 开启之后,每个表都有自己独立的表空间物理文件,所有的数据以及索引都会存储在该文件中
,这样方便备份以及恢复数据。
(2)段 (Segment):表空间是由各个段组成的,段一般分为数据段、索引段和回滚段
等。
- InnoDB 默认是基于
B + 树实现的数据存储
。 - 索引段: B + 树的非叶子节点。
- 数据段: B + 树的叶子节点。
- 回滚段:回滚数据。
(3)区 (Extent) / 页(Page):
- 区是表空间的单元结构,每个区的大小为
1MB
。 - 页是组成区的最小单元,页也是 InnoDB 存储引擎磁盘管理的最小单元,每个页的大小默认为
16KB
。 - 为了保证页的连续性,InnoDB 存储引擎每次从磁盘申请 4-5 个区。
(4)行(Row)
- InnoDB 存储引擎是面向列的(row-oriented),也就是说
数据是按行进行存放的
。 - 每个页存放的行记录也是有硬性定义的,最多允许存放 16KB/2-200 行,即 7992 行记录。
redo log 工作原理
InnoDB 的事务实现是基于事务日志redo log 和 undo log
实现的。
- redo log:重做日志,提供再写入操作,实现事务的持久性;redo log 又包括了内存中的
日志缓冲(redo log buffer)
以及保存在磁盘的重做日志文件(redo log file)
,前者存储在内存中,容易丢失,后者持久化在磁盘中,不会丢失。- Write Ahead Log 策略:InnoDB 的更新操作采用的是 Write Ahead Log 策略,即
先写日志,再写入磁盘
。当一条记录更新时,InnoDB 会先把记录写入到 redo log buffer 中,并更新内存数据
。- 可以通过参数
innodb_flush_log_at_trx_commit
自定义 commit 时,如何将 redo log buffer 中的日志刷新到 redo log file 中。
- 可以通过参数
- redo log 的大小是固定的,分别有多个日志文件采用循环方式组成一个循环闭环,当写到结尾时,会回到开头循环写日志
- 可以通过参数
innodb_log_files_in_group 和 innodb_log_file_size 配置日志文件数量和每个日志文件的大小
。
- 可以通过参数
- 脏页:Buffer Pool 中更新的数据未刷新到磁盘中。
- 触发脏页的刷新的条件:
- redo log 日志满了
- 系统内存不足时,需要将一部分数据页淘汰掉,如果淘汰的是脏页,需要先将脏页同步到磁盘;
- MySQL 认为空闲的时间,这种情况没有性能问题;
- MySQL 正常关闭之前,会把所有的脏页刷入到磁盘,这种情况也没有性能问题。
- 慢 SQL 监控中会发现偶尔会
出现一些用时稍长的 SQL
,这是因为脏页在刷新到磁盘时可能会给数据库带来性能开销,导致数据库操作抖动
。
- 触发脏页的刷新的条件:
- Write Ahead Log 策略:InnoDB 的更新操作采用的是 Write Ahead Log 策略,即
- undo log:回滚日志,提供回滚操作,保证事务的一致性。
往期精彩专栏内容,欢迎订阅:
🔗【八股消消乐】20250606:MySQL参数优化大汇总
🔗【八股消消乐】20250605:端午节产生的消费数据,如何分表分库?
🔗【八股消消乐】20250604:如何解决SQL线上死锁事故
🔗【八股消消乐】20250603:索引失效与优化方法总结
🔗【八股消消乐】20250512:慢SQL优化手段总结
🔗【八股消消乐】20250511:项目中如何排查内存持续上升问题
🔗【八股消消乐】20250510:项目中如何优化JVM内存分配?
🔗【八股消消乐】20250509:你在项目中如何优化垃圾回收机制?
🔗【八股消消乐】20250508:Java编译优化技术在项目中的应用
🔗【八股消消乐】20250507:你了解JVM内存模型吗?
🔗【八股消消乐】20250506:你是如何设置线程池大小?
🔗【八股消消乐】20250430:十分钟带背Duubo中大厂经典面试题
🔗【八股消消乐】20250429:你是如何在项目场景中选取最优并发容器?
🔗【八股消消乐】20250428:你是项目中如何优化多线程上下文切换?
🔗【八股消消乐】20250427:发送请求有遇到服务不可用吗?如何解决?
📌 [ 笔者 ] 文艺倾年
📃 [ 更新 ] 2025.6.7
❌ [ 勘误 ] /* 暂无 */
📜 [ 声明 ] 由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!