InnoDB内部结构——官方文档翻译

官方文档地址:14.4 InnoDB Architecture

1. Buffer Pool

Buffer pool是主内存中用于访问InnoDB缓存的表和索引(聚集索引,辅助索引)数据的一块区域。Buffer pool允许那些频繁使用的数据直接在内存中处理,从而加速整个处理过程。在专用的数据库服务器中,通常接近80%的物理内存被分配给buffer pool。

为了大容量读操作的效率,buffer pool被划分为可以保存多行数据的一系列页面。为了缓存管理的效率,buffer pool被实现为一系列页面的链表;使用变体的LRU算法,那些很少使用的数据将被标记为缓存过期。


2. Change Buffer

Change buffer是用于缓存辅助索引页(未加载至buffer pool中)变化的一种特殊数据结构。INSERT、UPDATE、DELETE操作(DML)会引起辅助索引页的缓存变化,当其它读操作将原始二级缓存页加载至buffer pool后,之前的缓存变化将被合并至buffer pool中。

不像聚集索引,辅助索引通常是不唯一的,且是以一种相对乱序的方式被插入辅助索引中。同样的,删除和更新操作也会影响在索引树中不相邻的辅助索引。当受影响的页被其它操作加载至buffer pool中时,合并缓存变化的操作会稍后进行,这样是为了避免大量的随机I/O从磁盘中读取辅助索引。

当系统大部分空闲或处于慢速停止运行时,清理操作会定期把更新的辅助索引页写入磁盘。比起把每个值立即写入磁盘,清理操作将一系列索引值写入磁盘块更加效率。

当有大量的辅助索引更新和受影响的行时,Change buffer的合并操作可能会花好几个小时。在此期间,磁盘I/O的增加将导致与磁盘相关的语句明显变慢。事务提交也会引起Change buffer的合并操作。事实上,mysql服务端的关闭和重启也会引起Change buffer的合并操作。

在内存中,Change buffer占据了InnoDB buffer pool的一部分。在磁盘中,Change buffer占据了系统表空间的一部分,因此索引更改在数据库重启时任然会被缓存。

Change buffer中缓存数据的类型是由配置文件中innodb_change_buffering这一项管理的。您也同样可以配置Change buffer的最大值。


3. Adaptive Hash Index

在系统具有适当的工作负载以及能为buffer pool提供充足内存的情况下,Adaptive Hash Index(AHI)使InnoDB表现得更像一个内存数据库,并且不用牺牲任何事物特性或可靠性。这种特性是由innodb_adaptive_hash_index开启,或者在系统启动时由–skip-innodb_adaptive_hash_index关闭。

基于观察到的搜索模式,mysql使用索引键的前缀构建哈希索引。键的前缀可以是任何长度,而且可能只有B-tree中的一些值出现在哈希索引中。哈希索引是根据那些经常被访问的索引页的需求构建的。

如果一个表几乎完全适合主内存,哈希索引可以通过将索引值转换为某种指针从而允许直接查找任何元素来加快查询速度。InnoDB有一个监控索引搜索的机制。如果InnoDB注意到查询可以从构建哈希索引中获益,那么它会自动这么做。

对于某些工作负载,哈希索引查找的加速比监视索引查找和维护哈希索引结构的额外工作要重要得多。有时,保护对访问Adaptive Hash Index的读/写锁会在高负载(如多个并发连接)下成为争用的来源。LIKE操作符和%通配符的查询也不会从AHI中受益。对于不需要Adaptive Hash Index的工作负载,关闭它可以减少不必要的性能开销。因为很难提前预测这个特性是否适合特定的系统,所以考虑使用一个实际的工作负载,通过运行基准测试来决定是否启用和禁用它。与早期版本相比,MySQL 5.6及更高版本的架构更改更适合禁用Adaptive Hash Index,尽管默认情况下仍然启用它。

MySQL 5.7对Adaptive Hash Index搜索系统进行了分区。每个索引都绑定到一个特定的分区,每个分区都由一个单独的锁闩保护。分区由innodb_adaptive_hash_index_parts配置选项控制。在早期的版本中,Adaptive Hash Index搜索系统被一个单一的锁闩保护,这可能会成为在高负载下的一个争用点。innodb_adaptive_hash_index_parts选项默认设置为8,最大设置为512。

哈希索引总是基于表上现有的B-tree索引构建的。InnoDB可以在为B-tree中定义的键的任何长度的前缀上构建一个哈希索引,这取决于InnoDB观察到的B-tree索引的搜索模式。哈希索引可以是部分的,只覆盖那些经常被访问的索引页。

您可以利用SHOW ENGINE INNODB STATUS命令输出的SEMAPHORES部分,监控Adaptive Hash Index的使用和对它的争用。如果您看到许多线程都在等待btr0sea.c中创建的RW-latch,那么禁用Adaptive Hash Index可能是有用的。


4. Redo Log Buffer

Redo Log Buffer是将数据写入redo log的内存区域。Redo Log Bufferd的大小由innodb_log_buffer_size配置选项定义。Redo Log Buffer定期刷新到磁盘上的日志文件。大的Redo Log Buffer允许大型事务运行,而无需在事务提交之前将Redo Log写入磁盘。因此,如果您有UPDATE、INSERT或DELETE许多行的事务,使用更大的Redo Log Buffer可以减少磁盘I/O。

innodb_flush_log_at_trx_commit配置选项控制Redo Log Buffer的内容如何写入日志文件,innodb_flush_log_at_timeout配置选项控制Redo Log的刷盘频率。


5. System Tablespace

InnoDB系统表空间包含InnoDB数据字典(用于与InnoDB相关的对象的元数据),并且是doublewrite buffer、change buffer、undo logs的存储区域。InnoDB数据字典系统表空间还包含在系统表空间中任何用户创建的表和索引数据。系统表空间被认为是一个共享表空间,因为它被多个表共享。

System Tablespace由一个或多个数据文件表示。默认情况下,在MySQL数据目录中创建一个名为ibdata1的系统数据文件。System Tablespace的大小和数量由innodb_data_file_path启动选项控制。


6. InnoDB Data Dictionary

InnoDB Data Dictionary由内部系统表组成,这些表包含用于跟踪对象(如表、索引和表列)的元数据。元数据位于InnoDB的物理系统表空间中。由于历史原因,数据字典元数据在一定程度上与存储在InnoDB表元数据文件(.frm文件)中的信息重叠。


7. Doublewrite Buffer

Doublewrite Buffer是位于系统表空间中的一个存储区域,InnoDB在此空间中写入从InnoDB缓冲池中刷新的页面,然后将页面写到数据文件的适当位置。只有在将页面刷新并写入到双写缓冲区之后,InnoDB才会将页面写入到正确的位置。如果在页面写入过程中存在操作系统、存储子系统或mysqld进程崩溃,InnoDB以后可以在崩溃恢复期间从双写缓冲区找到页面的完整副本。

尽管数据总是被写入两次,但Doublewrite Buffer不需要两倍的I/O开销,也不需要两倍的I/O操作。数据本身作为一个大的连续块被写入到Doublewrite Buffer,并使用一个对操作系统的fsync()调用。

在大多数情况下,双写缓冲区在默认情况下是启用的。要禁用双写缓冲区,请将innodb_doublewrite设置为0。

如果系统表空间文件(“ibdata文件”)位于支持原子写的Fusion-io设备上,则会自动禁用双写缓冲,所有数据文件都使用Fusion-io原子写。由于双写缓冲区设置是全局的,所以对于驻留在非fusion-io硬件上的数据文件,双写缓冲区也被禁用。此特性仅支持Fusion-io硬件,仅支持Linux上的Fusion-io NVMFS。为了充分利用这个特性,建议使用O_DIRECT的innodb_flush_method设置。


8. Undo Logs

Undo Log是与单个事务相关联的Undo Log记录的集合。Undo Log记录了如何撤消事务对聚集索引记录的最新更改。如果另一个事务需要查看原始数据(作为一致读取操作的一部分),则从Undo Log记录中检索未修改的数据。Undo Log存在于撤销日志段中,这些日志段包含在回滚段中。回滚段驻留在系统表空间、临时表空间和撤消表空间中。

InnoDB支持128个回滚段,其中32个保留为临时表事务的非重做回滚段。InnoDB为更新临时表(不包括只读事务)的每个事务都分配两个回滚段,一个重新启用的回滚段和一个不重做回滚段。只读事务只被分配为非重做回滚段,因为只读事务只允许修改临时表。

留下的96个可用的回滚段,每个段支持最多1023个修改数据的并发事务,总限制为大约96K,并假设事务不修改临时表。如果所有修改数据的事务也修改临时表,那么总的限制是大约32K。

InnoDB利用innodb_rollback_segments配置选项决定回滚段的个数。


9. File-Per-Table Tablespaces

File-Per-Table Tablespaces是一张表一个物理文件,它创建于自己的数据文件中而不是系统表空间中。当启用innodb_file_per_table选项时,InnoDB表都是在自己的表空间而不是系统表空间中创建。每个File-Per-Table Tablespaces都由一个.ibd数据文件表示,该文件在数据库目录中默认创建。

File-Per-Table Tablespaces支持动态和压缩的行格式,这些格式支持可变长度数据的页外存储和表压缩等特性。


10. General Tablespaces

使用CREATE TABLESPACE语法创建共享InnoDB表空间。General Tablespaces可以在MySQL数据目录之外创建,能够保存多个表、支持所有行格式。


11. Undo Tablespace

一个Undo Tablespace由一个或多个包含undo logs的文件组成。Undo Tablespace的数量由innodb_undo_tablespaces配置选项定义。innodb_undo_tablespaces将来会被弃用。


12. Temporary Tablespace

共享的临时表空间被用于创建非压缩的、用户创建的临时表和磁盘上的内部临时表。innodb_temp_data_file_path配置选项定义临时表空间数据文件的相对路径、名称、大小和属性。如果innodb_temp_data_file_path没有指定值,则默认行为是在innodb_data_home_dir目录中创建一个名为ibtmp1的自动扩展数据文件,该文件的大小略大于12MB。

专用临时表空间还意味着不再需要将临时表元数据保存到InnoDB系统表中。压缩临时表是使用ROW_FORMAT=COMPRESSED参数创建的临时表,在临时文件目录中的File-Per-Table表空间中创建。

临时表空间在正常关闭或初始化中止时删除,并在每次启动服务器时重新创建。临时表空间在创建时接收动态生成的空间ID。如果无法创建临时表空间,则拒绝启动。如果服务器意外停止,则不会删除临时表空间。在这种情况下,数据库管理员可以手动删除临时表空间或重新启动服务器,服务器将自动删除并重新创建临时表空间。

默认情况下,临时表空间数据文件是自动扩展的,并根据需要增加大小以适应磁盘上的临时表。例如,如果操作创建一个大小为20MB的临时表,那么创建时默认大小为12MB的临时表空间数据文件将扩展大小以适应它。当删除临时表时,释放的空间可以用于新的临时表,但是数据文件仍然保持扩展大小。

在使用大型临时表或大量使用临时表的环境中,自动扩展临时表空间数据文件可以变得很大。大型数据文件也可以由使用临时表的长时间运行的查询生成。

或者,您可以在操作系统上检查临时表空间的数据文件大小。默认情况下,临时表空间数据文件位于innodb_temp_data_file_path配置选项定义的目录中。如果未为该选项显式指定值,则在innodb_data_home_dir中创建一个名为ibtmp1的临时表空间数据文件,如果未指定,则默认为MySQL数据目录。

要回收临时表空间数据文件占用的磁盘空间,可以重新启动MySQL服务器。重新启动服务器将根据innodb_temp_data_file_path定义的属性删除并重新创建临时表空间数据文件。

或者,您可以配置default_tmp_storage_engine和internal_tmp_disk_storage_engine选项,它们分别定义了用于用户创建的存储引擎和磁盘上的内部临时表。这两个选项默认设置为InnoDB。MyISAM存储引擎为每个临时表使用一个单独的文件,在删除临时表时删除该文件。

临时表undo logs驻留在临时表空间中,用于临时表和相关对象。临时表undo logs不会被重新记录,因为它们不是崩溃恢复所必需的。它们只用于服务器运行时的回滚。这种特殊类型的undo logs可以避免redo log I/O,从而提高性能。InnoDB为修改临时表和相关对象的事务保留了32个回滚段。


13. Redo Log

redo log是在崩溃恢复期间使用的基于磁盘的数据结构,用于纠正不完整事务写入的数据。在正常操作期间,redo log编码请求,以更改来自SQL语句或低级API调用的InnoDB表数据。在系统意外关闭后,未及时写入磁盘文件的修改会在系统初始化过程中,并在连接被接受之前自动重做。

默认情况下,redo log在磁盘上表示为一组物理文件,命名为ib_logfile0和ib_logfile1。MySQL以循环方式写入redo log文件。redo log中的数据按照受影响的记录进行编码;这些数据统称为redo。数据通过redo log的通道由一个不断增加的LSN值表示。

与任何其他兼容ACID的数据库引擎一样,InnoDB在提交事务之前先刷入redo log。InnoDB使用group commit功能将多个此类刷入请求分组在一起,以避免每次提交一次刷入。对于组提交,InnoDB向日志文件发出一个写操作,以便对同时提交的多个用户事务执行提交操作,从而显著提高吞吐量。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值