InnoDB存储引擎架构

InnoDB存储引擎架构Mysql 中提供了多种存储引擎 其中使用最常用的就是 InnoDB 和 MyISAM 因为 MyISAM 不支持事务 所以在 Mysql8 的时候被移除了 我们使用 Mysql 大多数情况下没有选择存储引擎而是使用了默认的 InnoDB 本文简单介绍了 InnoDB 存储引擎 文章对官方文档进行了简单的摘要讲解 有对 InnoDB 感兴趣的可以直接看官方文档


前言

一、存储结构

在这里插入图片描述
上图是Mysql官方提供的InnoDB架构图,可以看到InnoDB主要分为内存架构和磁盘结构两部分。

内存结构

内存结构主要是针对的是数据及其操作,内存结构又分为Buffer Pool、Change Buffer、Adaptive Hash Index和Log Buffer四部分:

  • Buffer Pool: 缓冲池,正常情况下直接从磁盘进行IO读取数据的效率是非常慢的,所以在InnoDB中提供了数据缓冲池,数据缓冲池里面不直接存放数据而是存放的Page页,将数据存放在了Page页中,在缓冲池Page页是通过链表形式来存放的。
    Page页有三种状态:空闲状态、使用状态和被修改状态,被修改状态也叫脏页,正常情况下对数据进行修改操作的时候先修改的是Page里面的数据,然后再把数据刷到文件中。
  • Change Buffer: 写缓冲区,正常情况下修改数据是先修改的缓冲池中Page的数据,但是缓冲池肯定不是所有的数据,而修改数据没有对应的Page数据的时候并不会直接把数据加载到缓冲池中去,而是放在了写缓冲区中记录,等到数据被读取的时候再把数据合并到缓冲池中。
  • Adaptive Hash Index: 自适应Hash索引,InnoDB存储引擎会根据Page页的访问频率和模式建立对应的Hash索引,这个索引是根据查询情况自动建立的,所以称为自适应Hash索引。
  • Log Buffer: 日志缓冲区,主要用来保存写入磁盘的(Redo/Undo)日志文件,日志缓冲区会定期刷新到磁盘log文件中,这样不用每次日志都进行磁盘IO操作,提高效率。

磁盘结构

磁盘结构主要针对的是表和表空间,磁盘结构分为Tablespaces、InnoDB Data Dictionary、Doublewrite Buffer、Redo Log和Undo Logs。

  • Tablespaces: 表空间,对于表空间大家应该都不陌生,用来存储表结构和数据的。表空间又被分为系统表空间、独立表空间、通用表空间、临时表空间等多种类型。
  • InnoDB Data Dictionary: 数据字典,InnoDB数据字典由内部系统表组成,这些表包含用于查找表、索引和表字段等对象的元数据。
  • Doublewrite Buffer: 双写缓冲区,我们知道数据修改先修改的Page页后又刷到磁盘的,在刷到磁盘前这些数据会先存放在双写缓存区中,双写缓存区是用来保障数据写入磁盘时候出现问题的备份。
  • Redo Logs: 重做日志,记录了所有缓冲池修改的数据,修改数据的时候先写日志,后修改的缓冲区,假设修改写入操作的时候数据库崩溃了或停电了,等下次启动通过重做日志来保持数据的正确性。
  • Undo Logs: 撤销日志,撤销日志是事务开始之前保存的数据备份,主要用来事务的回滚操作还原原来的数据。

二、线程模型

InnoDB中主要有Master Thread、IO Thread、Purge Thread和Page Cleaner Thread四种类型的线程来做数据处理。

  • Master Thread: 这是InnoDB中的主线程,主要负责其他线程的调度。
  • IO Thread: 这是InnoDB中用来做读写操作的线程,使用的AIO的方式有利于提高数据库性能。
  • Purge Thread: 这是用来回收undoLog的,undoLog是为了事务回滚使用的,当事务提交之后之前保存的undoLog就没用了需要回收。
  • Page Cleaner Thread: 这是同步Page页数据到磁盘的线程,修改数据后先修改Page页中的数据,后面通过这个线程来把数据同步刷新到磁盘。

三、数据文件

通过show variables like ‘%datadir%’ 命令可以查询Mysql中的数据文件存放在了哪里
在这里插入图片描述
进入到提示的文件夹查看一下存放的文件信息
在这里插入图片描述
其中这个mysql.ibd文件就是Mysql中存储数据的文件,当数据库出现问题后也可以通过这个文件来恢复数据。
在这里插入图片描述
这是官网给出的InnoDB数据文件的结构。可以看到是Tablespace(表空间) -> Segment(段) -> Extent(区) -> Page(页) -> Row(行)这样层层包含的关系的,Row就是我们最终看到的数据库中一行一行的数据。
在这里插入图片描述
Page页的大小默认是16k,可以通过show variables like ‘%innodb_page_size%’ 命令查看
在这里插入图片描述
尽管在Page中Row记录的大小是不缺定的,但是我们还是可以大体估算一个数的,如果能在Page中存放更多的Row,那么执行查询SQL语句将会变的更快。如何在Page中存放更多的Row,这与Row的行格式有一定的关系,行格式决定了行是如何物理存储的,这反过来又会影响查询和DML操作的性能。









InnoDB中Row的行格式分为REDUNDANT、COMPACT、 DYNAMIC和COMPRESSED四种。

  • REDUNDANT : 使用REDUNDANT行格式,表会将变长列值的前768字节存储在B树节点的索引记录中,其余的存储在溢出页上。对于大于等于786字节的固定长度字段InnoDB会转换为变长字段,以便能够在页外存储(如果某字段的信息过长,这时候会被单独分配空间叫作溢出页,该字段叫做页外列)。
  • COMPACT: 与REDUNDANT行格式相比,COMPACT行格式减少了约20%的行存储空间,但代价是增加了某些操作的CPU使用量。简单的说就是牺牲了部分CPU的性能来增加了磁盘IO的性能,如果CPU比较好而磁盘IO性能差点的服务器可以设置为该格式。
  • DYNAMIC: 使用DYNAMIC行格式,InnoDB会将表中比较长的可变长度的列值完全存储在页外,而索引记录只包含指向溢出页的20字节指针。DYNAMIC行格式支持大索引前缀,最多可以为3072字节。
  • COMPRESSED: COMPRESSED行格式提供与DYNAMIC行格式相同的存储特性和功能,但增加了对表和索引数据压缩的支持,如果存放长数据比较多的数据库可以考虑使用这种格式。

可以看到InnoDB中对于Row的处理比较注重对变长字段的处理,像一些VARCHAR、VARBINARY、TEXT等变长字段的长度是不固定的,占用的空间大小也是不固定的,如果内容太长非常占用空间。其中DYNAMIC格式相较于REDUNDANT格式的处理是只保留了B-Tree子节点指向,对于长的可变行完全行溢出,占用更小的空间意味着Page页可以存放更多的行,效率更快一点。Mysql之后默认使用的行格式为DYNAMIC。可以使用命令show variables like ‘innodb_%format’; 查看
在这里插入图片描述

阿里巴巴JAVA开发手册的处理

  1. 【强制】如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
  2. 【强制】varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/214791.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午3:26
下一篇 2026年3月18日 下午3:26


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号