之前在写存储引擎的时候只是简单的介绍了下引擎是干什么的以及一些引擎的特点,这篇重点包括InnoDB引擎的逻辑存储结构,架构,事务原理和MVCC
InnoDB引擎的逻辑存储结构的存储引擎之前有简单介绍过:表空间->段->区->页->行
- 表空间(.ibd文件):一个mysql实例可以对应多个表空间,用于存储记录,索引等数据
- 段:分为数据段,索引段和回滚段,InnoDB中所有的数据是基于索引组织的,数据段则是B+树的叶子节点,索引段是非叶子节点
- 区:表空间的单元结构,每个区的大小为1M,默认情况下InnoDB引擎的页大小为16KB,所以1个区有64个连续的页
- 页:InnoDB引擎管理磁盘最小的单元,为保证页的连续性,InnoDB引擎每次会申请4-5个区
- 行:InnoDB引擎存储的数据按照行进行存放
MySQL从5.5版本开始就使用InnoDB引擎作为默认引擎,因为InnoDB擅长处理事务,且具有崩溃恢复特性
InnoDB的架构分为内存结构和磁盘结构,我们分开讲
内存结构包括4个区域:缓冲池(Buffer Pool),更改缓冲区(Change Buffer),日志缓冲区(Log Buffer)和自适应哈希索引(Adaptive Hash Index)
缓冲池用于缓存磁盘上经常操作的真实数据,在执行增删改查的操作的时候会先操作缓冲池里面的数据(没有则去磁盘加载并缓存),然后以一定的频率刷新到磁盘,减少磁盘的读写操作
缓冲池以页为单位,底层采用链表进行管理,根据状态将页分为三种类型:
free page:空闲页
clean page:被使用的页,数据没有被修改
dirty page:脏页,被使用且数据被修改,页里面的数据和磁盘数据不一致
更改缓冲区针对的是非唯一二级索引页,因为二级索引通常是非唯一的,并且插入的顺序比较随机,但是如果删除或更新某个二级索引也是会影响到其它二级索引的,所以如果每次直接操作磁盘的话也会造成大量的磁盘IO操作
在执行DML语句的时候如果这些数据页不在缓冲池中,那么不会直接操作磁盘,而是将数据变更存储在更改缓冲区中,在后续数据被读取的时候再将其合并到缓冲池中
用于优化对缓冲池的查询,InnoDB引擎会监控对索引页的查询,如果觉得hash索引可以提升速度的话就会建立hash索引,这就是自适应哈希索引
自适应哈希索引是系统根据情况自动完成的,不需要人工干预
保存要写入到磁盘的日志数据(redo log,undo log),默认大小为16MB
日志缓冲区的日志会定期刷新到磁盘中,日志缓冲区大小可调节
innodb_log_buffer_size 日志缓冲区大小的参数
innodb_flush_log_at_trx_commit 日志刷新到磁盘的时机,0是每秒将日志写入然后刷新,1是事务提交的时候写入并刷新,2是事务提交后写入,之后每秒刷新到磁盘
磁盘结构区域比较多,包括系统表空间(System Tablespace),文件表空间(File-Per-Table Tablespaces),通用表空间(General Tablespaces),撤销表空间(Undo Tablespaces),临时表空间(Temporary Tablespaces),双写缓冲区(Doublewrite Buffer Files)和重做日志(Redo Log)
是更改缓冲区的存储区域,这是8.0之后重新规划的,之前的版本还会存放其它的东西
每个表都会有一个这样的空间,里面包含表自己的数据和索引