存储引擎InnoDB | 青训营笔记

106 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 10 天
本文主要介绍了MySQL中的InnoDB引擎的基本结构,以及其如何保证了事务的ACID特性。

存储引擎

存储引擎负责了数据的底层存储、管理和访问工作。各大RDBMS存储引擎的设计都有不少的差异,这里选择MySQL的InnoDB存储引擎来向大家做一个介绍:

101.jpeg

  • Buffer Pool:存储引擎位于内存中的重要结构,用于缓存数据,减少磁盘IO的开销。写入时,先将数据写入缓冲池种,再定期刷新到磁盘;读取时,将读到的页放到缓冲池种,下次再读取相同的页时,会首先判断该页是否在缓冲池中,若在缓冲池中则直接从缓冲池中返回。

  • Page:数据存储的最基本单位,一般为16KB。

  • B+u Tree:InnoDB中最常用的索引结构。

  • redo log叫做重做日志,是用来实现事务的持久性。在事务提交之前,将修改信息记录到redo log中,因此针对宕机或断电导致buffer pool中的数据未同步到磁盘上的情况,系统在重启后通过redo log恢复最新数据。

  • undo log 叫做回滚日志,用于记录数据被修改前的信息。他正好跟前面所说的重做日志所记录的相反,重做日志记录数据被修改后的信息。undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。这样保障了事务的原子性。

事务引擎

事务引擎实现了数据库的ACID能力,这里还是以MySQL的InnoDB为例来介绍数据库内部是通过哪些技术来实现ACID:

  • Atomicity:InnoDB中通过undo日志实现了数据库的原子性,通过Undo Log,数据库可以回滚到事务开始的状态;

  • Isolation:通过Undo Log实现MVCC(多版本并发控制),降低读写冲突。

  • Durability:通过Redo Log(一种WAL实现方式)来保证事务在提交后一定能持久化到磁盘中。

💡 随机IO(随机IO是指读写操作时间连续,但访问地址不连续,随机分布在磁盘的地址空间中。)和写放大都是方案一的问题
  • Consistency:一致性本质上是一种业务层的限制。

课后思考

  1. WAL 日志到底是如何保证数据的持久化,宕机后数据不丢失的?相比于其他方案,WAL 日志都有什么优势?

    —WAL(Write Ahead Log)预写日志。在所有WAL系统中,所有修改在提交之前都要先写入log文件,也就是修改并不直接写入到数据库文件中,而是写入到另外一个称为 WAL 的文件中;如果事务失败,WAL 中的记录会被忽略,撤销修改;如果事务成功,它将在随后的某个时间被写回到数据库文件中,提交修改。

    优点:

    读和写可以完全地并发执行,不会互相阻塞;

    WAL 在大多数情况下,拥有更好的性能

    磁盘 I/O 行为更容易被预测。

    使用更少的 fsync()操作,减少系统脆弱的问题。

  2. 除了 Undo Log 之外,是否还有其他方案可以实现 MVCC?

    —除了Undo Log之外,还有shadow paging的方式。例如PostgreSQL就是采用这种方式。这种方式的特点是,在数据页面中同时保留了一行数据的多个历史版本,通过trx_id来区分。

  3. 基于代价的优化器一般需要考虑哪些代价?

    —一般需要考虑IO消耗、网络消耗、CPU消耗等

  4. 执行器的执行模型,除了本课中提到的火山模型是否还有其他模型?相比于火山模型有什么优劣势?

    —还有向量化模型(每个operator每次操作计算不再是一行数据,而是一批数据,计算完成后向上层算子返回一个batch。优势:函数调用次数降低为1/N;CPU cache的命中率更高;可以利用CPU提供的SIMD机制。缺点:对于单行数据的处理并没有优势。

    编译执行模式(将所有操作封装在一个函数中),优势:大幅降低了函数调用代价。

  5. InnoDB 的 B+ Tree 是怎么实现的?

    —所有记录节点都是按照键值大小顺序的放在同一层的叶子节点中。

    非叶子节点不存放数据值,而只存放索引值,即key。

    叶子节点处于同一层,左右通过指针链接,可以很好的顺序读取和排序

  6. InnoDB 的 buffer pool 是怎么实现页面管理和淘汰的?

    —InnoDB的buffer pool通过一个hash_map<page_id, page_ptr>来实现页面的快速查找访问,通过一个LRU来实现页面的冷热淘汰管理。