Adaptive Hash Index,自适应哈希索引。InnoDB引擎会监控对索引页的查询,如果发现建立哈希索引可以带来性能上的提升,就会建立哈希索引,这种称之为自适应哈希索引,InnoDB引擎不支持手动创建哈希索引。

Log Buffer

日志缓冲区是存储要写入磁盘日志文件的一块数据内存区域,大小由变量innodb_log_buffer_size 控制,默认大小为16MB(5.6版本是8MB):

SHOW VARIABLES LIKE ‘innodb_log_buffer_size’;-- global级别,无session级别

上文讲述update语句更新流程一文中,我们只提到了Buffer Pool用来代替缓存区,通过本文对内存结构的分析,实际上Buffer Pool中严格来说还有Change Buffer,Log Buffer和Adaptive Hash Index三个部分,DML操作会缓存在Change Buffer区域,而写redo log之前会先写入Log Buffer,所以Log Buffer又可以称之为redo Log Buffer。

Log Buffer什么时候写入redo log

一个大的Log Buffer空间大允许运行大型事务,而无需在事务提交之前将redo log数据写入磁盘。Log Buffer中的数据会定期刷新到磁盘,那么Log Buffer的数据又是如何写入磁盘的呢?Log Buffer数据flush到磁盘有三种方式,通过变量innodb_flush_log_at_trx_commit 控制,默认为1。 |value|描述|

mysql double 数值相加_表空间

  • 当设置为0时,由于数据还在内存,所以崩溃后数据基本会被丢失
  • 当设置为2时,由于数据已经实时写到redo log了,如果磁盘文件没有被损坏,还是可以恢复的

另外,Mast Thread默认1s进行一次刷盘操作,这个可以通过变量innodb_flush_log_at_timeout控制,默认1s。

SHOW VARIABLES LIKE ‘innodb_flush_log_at_timeout’;-- global级别,无session级别

磁盘结构

InnoDB引擎的磁盘结构,从大的方面来说可以分为Tablespace和redo log两部分

Tablespace

Tablespace可以分为4大类,分别是:System Tablespace,File-Per-Table Tablespaces,General Tablespaces,Undo Tablespaces

System Tablespace

系统表空间中包括了 InnoDB data dictionary,doublewrite buffer, change buffer, undo logs 4个部分,默认情况下InnoDB存储引擎有一个共享表空间ibdata1,如果我们创建表没有指定表空间,则表和索引数据也会存储在这个文件当中,可以通过一个变量控制(后面会介绍)。

ibdata1文件默认大小为12MB,可以通过变量innodb_data_file_path来控制,改变其大小的最好方式就是设置为自动扩展。

innodb_data_file_path=ibdata1:12M:autoextend

上面表示默认表空间ibdata1大小为12MB,支持自动扩展大小。

当我们的文件达到一定的大小之后,比如达到了998MB,我们就可以另外开启一个表空间文件:

innodb_data_home_dir=
innodb_data_file_path=/ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend

关于上面的设置有3点需要注意:

  • innodb_data_home_dir如果不设置的话,那么就默认所有的表空间文件都在datadir目录下,而我们上面指定了2个不同路径,所以需要把innodb_data_home_dir设为空
  • autoextend这个属性,只能放在最后一个文件
  • 指定新的表空间文件名的时候,不能和现有表空间文件名一致,否则启动MySQL时会报错

当然,表空间可以增大,自然也可以减少,但是一般我们都不会去设置减少,而且减少表空间也相对麻烦,在这里就不展开叙述了。

InnoDB Data Dictionary

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

Doublewrite Buffer

Doublewrite Buffer,双写缓冲区,这个是InnoDB为了实现double write而设置的一块缓冲区,double write和上面的change buffer一个确保了可靠性,一个确保了性能的提升,是InnoDB中非常重要的两大特性。

我们先来看下面一张图:

mysql double 数值相加_mysql_02

InnoDB默认页的大小是16KB,而操作系统是4KB,如果存储引擎正在写入页的数据到磁盘时发生了宕机,可能出现页只写了一部分的情况,比如只写了 4K,这种情况叫做部分写失效(partial page write),可能会导致数据丢失。

可能有人会说,可以通过redo log来恢复,但是注意,redo log恢复数据有一个前提,那就是页没有损坏,如果页本身已经被损坏了,那么是没办法恢复的,所以为了确保万无一失,我们需要先保存一个页的副本,如果出现了上面的极端情况,可以用页的副本结合redo log来恢复数据,这就是double write技术。

double write也是由两部分组成,一部分是内存中的double write buffer,大小为2MB,另一部分是物理磁盘上的共享表空间中的连续128个页,大小也是2MB,写入流程如下图(图片来源于《MySQL技术内幕 InnoDB存储引擎》):

mysql double 数值相加_表空间_03

double write机制会使得数据写入两次磁盘,但是其并不需要两倍的I/O开销或两倍的I/O操作。通过对操作系统的单个fsync()调用,数据以一个大的顺序块的形式写入到双写入缓冲区。

在大多数情况下默认启用了doublewrite缓冲区。要禁用doublewrite缓冲区,可通过将变量innodb_doublewrite设置为0即可。

Undo Logs

undo log记录了单个事务对聚集索引数据记录的最近一次修改信息,用来保证在必要时实现回滚,如果另一个事务需要在一致性读操作中查看原始数据,则从undo日志记录中检索未修改的数据,也就是说MVCC机制也依赖于undo log来实现。

与redo log不同的是,undo log存储的是逻辑日志,undo log分为两种类型:

  • insert undo log 由insert操作产生,由于插入数据操作只对当前事务可见,所以事务提交之后可以直接删除
  • update undo log 由update和delete操作产生,由于要实现MVCC多版本并发控制,故而update undo log在事务提交之后不能直接删除,而是最后由后台线程(Purge Thread或者Master Thread)来最终判断是否可以删除

注意,update undo log最终到底由哪个线程来执行purge操作,可以通过配置文件来配置实现,:

[mysqld]
innodb_purge_thread=1

1表示由独立线程Purge Thread来实现,否则由主线程Master Thread来实现

File-Per-Table Tablespaces

独占表空间,通过变量innodb_file_per_table控制,在MySQL5.6开始,默认是开启的

innodb_file_per_table=ON

开启后,则每张表会开辟一个表空间,这个文件就是数据目录下的 ibd 文件,不同引擎生成的文件不一样。独占表空间存放表的索引和数据,其他数据如回滚(undo)信息,插入缓冲索引页、系统事务信息,二次写缓冲(Double write buffer)等还是存放在原来的共享表空间内。

General Tablespaces

General Tablespaces,通用表空间,和系统表空间idata1类似,一般指的是我们自己使用CREATE tablespace语法创建的共享InnoDB表空间。 创建语法为:

CREATE TABLESPACE tablespace_name
ADD DATAFILE ‘file_name’
[FILE_BLOCK_SIZE = value]
[ENGINE [=] engine_name]

在数据目录中创建一个通用表空间:

CREATE TABLESPACE ts1 ADD DATAFILE ‘ts1.ibd’ Engine=InnoDB;

在数据目录之外创建一个通用表空间:

CREATE TABLESPACE ts1 ADD DATAFILE ‘/my/tablespace/directory/ts1.ibd’ Engine=InnoDB;

然后我们再创建或者修改表的时候可以指定为创建的通用表空间:

CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1;
ALTER TABLE t2 TABLESPACE ts1;

Undo Tablespaces

Undo表空间包含Undo日志。Undo日志可以存储在一个或多个Undo表空间中,而不是系统表空间中。这种布局不同于默认配置,在默认配置中,undo log保存在系统表空间中。

Undo表空间的数量由innodb_undo_tablespaces变量定义。默认值是0:

SELECT @@innodb_undo_tablespaces;

Temporary Tablespace

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

临时表空间在正常关闭或初始化失败时被删除,并在每次服务器启动时重新创建。临时表空间在创建时会动态生成一个空间ID。如果无法创建临时表空间,MySQL会拒绝启动。如果服务器意外停止,临时表空间不会被删除。在这种情况下,我们可以进行手动删除临时表空间,或者重新启动服务器,从而自动删除和重新创建临时表空间。

可以通过如下语句查询临时表空间信息:

SELECT * FROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME=‘innodb_temporary’;

默认情况下,临时表空间数据文件会自动扩展和增加大小,以适应磁盘上的临时表,临时表的大小和ibdata1文件一样可以通过变量修改。

SHOW VARIABLES LIKE ‘innodb_temp_data_file_path’;-- 默认12MB大,可扩展
innodb_temp_data_file_path=ibtmp1:12M:autoextend

为了防止临时数据文件变得太大,可以配置innodb_temp_data_file_path选项来指定最大文件大小。