“InnoDB:InnoDB 磁盘结构:Tablespaces”的版本间差异

来自Wikioe
跳到导航 跳到搜索
无编辑摘要
 
(未显示同一用户的6个中间版本)
第1行: 第1行:
[[category:MySQL]]
[[category:MySQL文档]]


== 关于 ==
== 关于 ==
第24行: 第24行:


=== InnoDB 逻辑存储结构 ===
=== InnoDB 逻辑存储结构 ===
[[File:InnoDB 逻辑存储结构.png|800px]]
[[File:InnoDB 逻辑存储结构.png|600px]]


从 InnoDB 逻辑存储结构来看,所有的数据都被逻辑的存放在一个空间中,这个空间就叫做'''表空间'''(tablespace)。表空间由:段(segment)、区(extent)、页(page)组成。
从 InnoDB 逻辑存储结构来看,所有的数据都被逻辑的存放在一个空间中,这个空间就叫做'''表空间'''(tablespace)。表空间由:段(segment)、区(extent)、页(page)组成。


# '''段'''(segment)
# '''段'''(segment)
#: 段分为'''索引段''''''数据段''''''回滚段'''等。其中:
#: 段分为'''索引段'''(B+树的非叶子结点部分,即上图的“Non-leaf node segment”),'''数据段'''(B+树的叶子结点部分,即上图的“Leaf node segment”),'''回滚段'''(用于数据的回滚和多版本控制)等。一个段包含'''256'''个区('''256M'''大小)。
# 索引段就是非叶子结点部分,
#* 在InnoDB中,对段的管理都是有存储引擎自身完成的,DBA不能也没有必要对其进行空间。这和Oracle数据库中的自动段空间管理(ASSM)类似,从一定程度上简化了DBA对于段的管理
# 而数据段就是叶子结点部分,
# 回滚段用于数据的回滚和多版本控制。
#: 一个段包含'''256'''个区('''256M'''大小)。
# '''区'''(extent)
# '''区'''(extent)
#: 区是页的集合,一个区包含'''64'''个连续的页,默认大小为 '''1MB''' (64*16K)
#: 区是页的集合,一个区包含'''64'''个连续的页,默认大小为 '''1MB''' (64*16K)。【不论页的大小怎么变化,区的大小总是为 1M】
#* 在默认情况下,InnoDB存储引擎页的大小为 16KB,即一个区一共有 64 个连续的页。
#* InnoDB 1.0.x 开始引入压缩页,即每个页的大小可以通过参数“KEY_BLOCK_SIZE”设置为 2K、4K、8K,因此每个区对应页的数量就应该为 512、256、128。
#* InnoDB 1.2.x 开始新增了参数“innodb_page_size”,通过该参数可以将默认页的大小设置为 4K、8K。但是页中的数据库不是压缩。这时区中页的数量同样也为 256、128。
#* 当启用参数“innodb_file_per_table”后,创建的表默认大小是 96KB:在每个段开始时,先用32个页大小的碎片页去存放数据,在使用完这些页之后才开始申请64个连续的页。【?】
#*: 这样做的目的是:对于一些小表,或者是undo这类的段,可以在开始时申请较少的空间,节省磁盘容量的开销。
# '''页'''(page)
# '''页'''(page)
#: 页是 InnoDB 管理的最小单位,常见的有“FSP_HDR”,“INODE”,“INDEX”等类型。所有页的结构都是一样的,分为“文件头”(前38字节),“页数据”和“文件尾”(后8字节)。页数据根据页的类型不同而不一样。
#: 页是 InnoDB 管理的最小单位,常见的有“FSP_HDR”,“INODE”,“INDEX”等类型。所有页的结构都是一样的,分为“文件头”(前38字节),“页数据”和“文件尾”(后8字节)。页数据根据页的类型不同而不一样。
#: 每个空间都分为多个页,通常每页'''16 KiB'''。空间中的每个页面都分配有一个32位整数页码,通常称为“偏移量”(offset),它实际上只是页面与空间开头的偏移量(对于多文件空间,不一定是文件的偏移量)。因此,页面 0 位于文件偏移量 0,页面 1 位于文件偏移量 16384,依此类推。
#: 每个空间都分为多个页,通常每页'''16 KiB'''。空间中的每个页面都分配有一个 32 位整数页码,通常称为“偏移量”(offset),它实际上只是页面与空间开头的偏移量(对于多文件空间,不一定是文件的偏移量)。因此,页面 0 位于文件偏移量 0,页面 1 位于文件偏移量 16384(1个文件16KB的偏移,即:16 x 1024 = 16384),依此类推。
#*(InnoDB 的数据限制为64TiB,这实际上是每个空间的限制,这主要是由于页码是32位整数与默认页大小的组合: 2^32 x 16 KiB = 64 TiB )
#*(InnoDB 的数据限制为 64TiB,这实际上是每个空间的限制,这主要是由于页码是 32 位整数与默认页大小的组合: 2^32 x 16 KiB = 64 TiB )


 
==== 关于“页” ====
关于“页”:
:[[File:InnoDB 页(page)结构.png|400px]]
:[[File:InnoDB 页(page)结构.png|600px]]
InnoDB 磁盘管理的最小单位。如图所示,每个page都有 38 个字节的 FIL header,以及 8 个字节的 FIL trailer(FIL 是 file 的简称)。FIL header 包含了一个表示 page type 的字段,这个字段用来确定这个 page 数据的结构。
如图所示,每个page都有 38 个字节的 FIL header,以及 8 个字节的 FIL trailer(FIL 是 file 的简称)。FIL header 包含了一个表示 page type 的字段,这个字段用来确定这个 page 数据的结构。


FIL header 和 trailer 示意图如下所示:
FIL header 和 trailer 示意图如下所示:
:[[File:InnoDB FIL header和trailer示意图.png|600px]]
:[[File:InnoDB FIL header和trailer示意图.png|400px]]
其中:
其中:
* checksum: 4个字节32位checksum保存在header中。
* checksum: 4个字节32位checksum保存在header中。
第205行: 第206行:
mysql> SET GLOBAL innodb_file_per_table=ON;
mysql> SET GLOBAL innodb_file_per_table=ON;
</syntaxhighlight>
</syntaxhighlight>
NOTE:
对于启用了“innodb_file_per_table”的参数选项,需要注意的是 ,每张表的表空间内存放的只是数据、索引和插入缓冲 ,其他类的数据,如撤销(Undo)信息、系统事务信息、 二次写缓冲 (double write buffer ) 等还是存放在原来的共享表空间内。这也就说明了另一个问题:'''即使在启用了参数innodb_file_per_table之后,共享表空间还是会不断地增加其大小'''。


=== 独占表空间数据文件 ===
=== 独占表空间数据文件 ===
第253行: 第258行:


== 常规表空间 ==
== 常规表空间 ==
常规表空间是<big>使用“'''CREATE TABLESPACE'''”语法创建的共享 InnoDB 表空间</big>。
=== 常规表空间功能 ===
常规表空间功能提供以下功能:
# 类似于系统表空间,常规表空间是'''共享表空间,可以存储多个表的数据'''。
# 常规表空间比独占表空间具有潜在的内存优势。服务器在表空间的生存期内将表空间元数据保留在内存中。与独占表空间中的相同数量的表相比,较少的常规表空间中的多个表为表空间元数据消耗的内存更少。
# 常规表空间数据文件可以放置在相对于 MySQL 数据目录或独立于 MySQL 数据目录的目录中,这为您提供了独占表空间的许多数据文件和存储管理功能。与每表文件表空间一样,将数据文件放置在 MySQL 数据目录之外的功能使您可以分别管理关键表的性能,为特定表设置 RAID 或 DRBD 或将表绑定到特定磁盘。【?】
# 常规表空间支持 Antelope 和 Barracuda 文件格式【???】,因此支持所有表行格式和相关功能。支持两种文件格式,常规表空间不依赖于“innodb_file_format”或“innodb_file_per_table”设置,这些变量也不影响常规表空间。
# “TABLESPACE”选项可以与“CREATE TABLE”一起使用,以在常规表空间,独占表空间或系统表空间中创建表。
# “TABLESPACE”选项可与“ALTER TABLE”一起使用,以在常规表空间,独占表空间和系统表空间之间移动表。以前,不可能将表从每个表文件表空间移至系统表空间。使用常规表空间功能,您现在可以这样做。
=== 创建常规表空间 ===
常规表空间是使用“'''CREATE TABLESPACE'''”语法创建的。
<syntaxhighlight lang="mysql">
CREATE TABLESPACE tablespace_name
    ADD DATAFILE 'file_name'
    [FILE_BLOCK_SIZE = value]
        [ENGINE [=] engine_name]
</syntaxhighlight>
* 常规表空间可以在数据目录中或在其外部创建。为避免与隐式创建的独占表空间冲突,'''不支持在数据目录下的子目录中创建常规表空间'''。
** 在数据目录之外创建常规表空间时,该目录必须在创建表空间之前存在。
* 在 MySQL 数据目录之外创建常规表空间时,会在 MySQL 数据目录中创建“'''.isl'''”文件。【?】
示例:
# 在数据目录中创建常规表空间:
#: <syntaxhighlight lang="mysql">
mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
</syntaxhighlight>
# 在数据目录之外的目录中创建常规表空间:
#: <syntaxhighlight lang="mysql">
mysql> CREATE TABLESPACE `ts1` ADD DATAFILE '/my/tablespace/directory/ts1.ibd' Engine=InnoDB;
</syntaxhighlight>
#* 您可以指定相对于数据目录的路径,只要表空间目录不在数据目录下即可。在此示例中,my_tablespace 目录与数据目录处于同一级别:
#*: <syntaxhighlight lang="mysql">
mysql> CREATE TABLESPACE `ts1` ADD DATAFILE '../my_tablespace/ts1.ibd' Engine=InnoDB;
</syntaxhighlight>
* “ENGINE = InnoDB”子句必须定义为“CREATE TABLESPACE”语句的一部分,或者 InnoDB 必须定义为默认存储引擎(default_storage_engine=InnoDB)。
=== 将表添加到常规表空间 ===
创建 InnoDB 常规表空间后,可以使用“CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_name”或“ALTER TABLE tbl_name TABLESPACE [=] tablespace_name”将表添加到表空间。
示例:
# CREATE TABLE:
#: <syntaxhighlight lang="mysql">
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1;
</syntaxhighlight>
# ALTER TABLE:
#: <syntaxhighlight lang="mysql">
mysql> ALTER TABLE t2 TABLESPACE ts1;
</syntaxhighlight>
* 在 MySQL 5.7.24 中已弃用了将表分区放置在共享表空间中的支持,并且在将来的 MySQL 版本中将删除该支持。【?】
=== 常规表空间行格式支持【????????】 ===
=== 使用“ALTER TABLE”在表空间之间移动表 ===
您可以将“ALTER TABLE”与“TABLESPACE”选项一起使用,以将表移至现有的常规表空间,新的独占表空间或系统表空间。
# 要将表从独占表空间或系统表空间移至常规表空间,请指定常规表空间的名称。
#* 常规表空间必须存在。
#:<syntaxhighlight lang="mysql">
ALTER TABLE tbl_name TABLESPACE [=] tablespace_name;
</syntaxhighlight>
# 要将表从常规表空间或独占表空间移至系统表空间,请指定“'''innodb_system'''”作为表空间名称。
#:<syntaxhighlight lang="mysql">
ALTER TABLE tbl_name TABLESPACE [=] innodb_system;
</syntaxhighlight>
# 要将表从系统表空间或常规表空间移至独占表空间,请指定“'''innodb_file_per_table'''”作为表空间名称。
#:<syntaxhighlight lang="mysql">
ALTER TABLE tbl_name TABLESPACE [=] innodb_file_per_table;
</syntaxhighlight>
NOTE:
* “ALTER TABLE ... TABLESPACE”操作'''始终会导致整个表的重建''',即使“TABLESPACE”属性与其之前的值相比也没有变化。
* “ALTER TABLE ... TABLESPACE”语法'''不支持将表从临时表空间移动到持久表空间'''。
* “DATA DIRECTORY”子句与“CREATE TABLE ... TABLESPACE=innodb_file_per_table”一起允许,但不支持与“TABLESPACE”选项结合使用。
* 从加密表空间中移动表时有限制。
=== 删除常规表空间 ===
“DROP TABLESPACE”语句用于删除 InnoDB 常规表空间。
* “DROP TABLESPACE”'''操作之前,必须从表空间中删除所有表'''。如果表空间不为空,则返回错误。
使用类似于以下内容的查询来标识常规表空间中的表。
<syntaxhighlight lang="mysql" highlight="2,3">
mysql> SELECT a.NAME AS space_name, b.NAME AS table_name
    FROM INFORMATION_SCHEMA.INNODB_TABLESPACES a,
      INFORMATION_SCHEMA.INNODB_TABLES b
    WHERE a.SPACE=b.SPACE AND a.NAME LIKE 'ts1';
+------------+------------+
| space_name | table_name |
+------------+------------+
| ts1        | test/t1    |
| ts1        | test/t2    |
| ts1        | test/t3    |
+------------+------------+
</syntaxhighlight>
NOTE:
* 如果对空的通用表空间的“DROP TABLESPACE”操作返回错误,则该表空间可能包含由服务器 Export 中断的“ALTER TABLE”操作留下的孤立临时表或中间表。
* 删除表空间中的最后一个表时,一般的 InnoDB表空间不会自动删除。'''必须使用“DROP TABLESPACE tablespace_name”明确删除表空间'''。
* '''常规表空间不属于任何特定数据库'''。 “DROP DATABASE”操作可以删除属于常规表空间的表,但是'''即使“DROP DATABASE”操作删除了属于该表空间的所有表,也不能删除该表空间'''。必须使用“DROP TABLESPACE tablespace_name”显式删除常规表空间。
* 与系统表空间类似,截断或删除存储在通用表空间中的表会在通用表空间“.ibd”数据文件内部内部创建可用空间,该可用空间仅可用于新的 InnoDB 数据。在“DROP TABLE”操作期间删除每表文件表空间时,'''不会将空间释放回 os'''。
* “tablespace_name”是 MySQL 中'''区分大小'''写的标识符。
=== 常规表空间限制 ===
* '''生成的表空间或现有表空间不能更改为常规表空间'''。
* 不支持创建临时通用表空间。
* 常规表空间'''不支持临时表'''。
* 通用表空间中存储的表只能在支持通用表空间的 MySQL 版本中打开。
* 与系统表空间类似,截断或删除存储在通用表空间中的表会在通用表空间“.ibd”数据文件内部内部创建可用空间,该可用空间仅可用于新的 InnoDB 数据。空间不会像独占表空间那样释放回 os。
*: 此外,驻留在共享表空间(通用表空间或系统表空间)中的表的表复制“ALTER TABLE”操作可以增加表空间使用的空间量。此类操作需要与表中的数据以及索引一样多的额外空间。表复制“ALTER TABLE”操作所需的额外空间不会像每个表文件表空间那样释放回 os。
* 属于常规表空间的表不支持“ALTER TABLE ... DISCARD TABLESPACE”和“ALTER TABLE ...IMPORT TABLESPACE”。
* 在源和副本位于同一主机上的复制环境中,不支持“ADD DATAFILE”子句,因为这会导致源和副本在同一位置创建相同名称的表空间。【?】
* 在 MySQL 5.7.24 中已弃用了将表分区放置在常规表空间中的支持,并且在将来的 MySQL 版本中将删除该支持。【?】
== 撤消(Undo)表空间【?????】 ==
撤消表空间包含'''撤消日志''',撤消日志是撤消日志记录的集合,其中包含有关如何通过事务撤消对聚集索引记录的最新更改的信息。
* 撤消日志存在于“撤消日志段”中,撤消日志段包含在“回滚段”中。“'''innodb_rollback_segments'''”变量定义分配给每个撤消表空间的回滚段的数量。
Undo logs 可以存储在一个或多个 undo tablespaces 中,而不是 system tablespace 中。此布局不同于 undo logs 位于 system tablespace 中的默认配置。撤消日志的 I/O 模式使撤消表空间成为 SSD 存储的理想候选者,同时将系统表空间保留在硬盘存储上。
InnoDB 使用的撤消表空间的数量由“innodb_undo_tablespaces”配置选项控制。仅在初始化 MySQL 实例时才能配置此选项。此后无法更改。【innodb_undo_tablespaces 配置选项已弃用,在以后的版本中将被删除。】
撤消表空间和这些表空间中的单个 segments 不能删除。但是,存储在撤消表空间中的撤消日志可以被截断。
<!--
=== 配置撤消表空间【???】 ===
要为 MySQL 实例配置撤消表空间,请执行以下步骤:
* 【撤消表空间的数量只能在初始化 MySQL 实例时配置,并且在实例生命周期内是固定的】
* 使用“innodb_undo_directory”配置选项为撤消表空间指定目录位置。如果未指定目录位置,则在数据目录中创建撤消表空间。
* 使用“innodb_rollback_segments”配置选项定义回滚段的数量。从一个相对较低的值开始,然后随着时间的推移逐渐增加它,以检查对性能的影响。
** “innodb_rollback_segments”的默认设置为 '''128''',这也是最大值。
始终将一个回滚段分配给系统表空间,并为临时表空间(ibtmp1)保留 32 个回滚段。因此,要将回滚段分配给撤消表空间,请将“innodb_rollback_segments”设置为大于 33 的值。例如,如果您有两个撤消表空间,则将“innodb_rollback_segments”设置为 35 可以为两个撤消表空间中的每个分配一个回滚段。回滚段以循环方式分布在撤消表空间中。




== 撤消(Undo)表空间 ==
配置单独的撤消表空间时,系统表空间中的回滚段将变为非活动状态。
* 使用“innodb_undo_tablespaces”选项定义撤消表空间的数量。在 MySQL 实例的生命周期中,指定的还原表空间数量是固定的,因此,如果不确定最佳值,请从高端进行估算。
* 使用您选择的选项值创建一个新的 MySQL 测试实例。
* 在测试实例上使用实际的工作负载,并使用与生产服务器类似的数据量来测试配置。
* 对 I/O 密集型工作负载的性能进行基准测试。
* 定期增加“innodb_rollback_segments”的值并重新运行性能测试,直到 I/O 性能没有进一步的提高。


=== 截断撤消表空间 ===
截断撤消表空间要求 MySQL 实例至少具有两个活动的撤消表空间,以确保一个撤消表空间保持活动状态,而另一个撤消表空间被脱机以被截断。
* 撤消表空间的数量由“'''innodb_undo_tablespaces'''”变量定义,默认值为 0。
使用此语句检查“innodb_undo_tablespaces”的值:
<syntaxhighlight lang="mysql">
mysql> SELECT @@innodb_undo_tablespaces;
+---------------------------+
| @@innodb_undo_tablespaces |
+---------------------------+
|                        2 |
+---------------------------+
</syntaxhighlight>
要截断撤消表空间,请启用“innodb_undo_log_truncate”变量。例如:
<syntaxhighlight lang="mysql">
mysql> SET GLOBAL innodb_undo_log_truncate=ON;
</syntaxhighlight>
* 启用“innodb_undo_log_truncate”变量后,超过“innodb_max_undo_log_size”变量定义的大小限制的撤消表空间将被截断。【“innodb_max_undo_log_size”变量是动态的,其默认值为 1073741824 字节(1024 MiB)】
启用“innodb_undo_log_truncate”变量后:
* 超过“innodb_max_undo_log_size”设置的撤消表空间被标记为被截断。以循环方式选择撤消表空间以进行截断,以避免每次都截断相同的撤消表空间。
* 驻留在选定撤消表空间中的回滚段将变为非活动状态,以便不将其分配给新事务。允许当前正在使用回滚段的现有事务完成。
* purge 系统释放不再使用的回滚段。
* 撤消撤消表空间中的所有回滚段后,将运行 truncate 操作并将撤消表空间截断为其初始大小。撤消表空间的初始大小取决于“innodb_page_size”值。对于默认的 16KB 页面大小,初始撤消表空间文件大小为 10MiB。对于 4KB,8KB,32KB 和 64KB 页面大小,初始撤消表空间文件大小分别为 7MiB,8MiB,20MiB 和 40MiB。
** 截断操作后撤消表空间的大小可能会大于初始大小,这是由于在操作完成后立即使用撤消表空间。
** “innodb_undo_directory”变量定义撤消表空间文件的位置。如果未定义“innodb_undo_directory”变量,则撤消表空间位于数据目录中。
* 重新激活回滚段,以便可以将其分配给新事务。
==== 加快截断撤消表空间的速度 ====
'''清除线程负责清空和截断撤消表空间'''。默认情况下,清除线程查找撤消表空间,以在每次清除调用被执行 '''128''' 次后截断一次。清除线程查找要删除的表空间的频率由“innodb_purge_rseg_truncate_frequency”变量控制,该变量的默认设置为 '''128'''.
<syntaxhighlight lang="mysql">
mysql> SELECT @@innodb_purge_rseg_truncate_frequency;
+----------------------------------------+
| @@innodb_purge_rseg_truncate_frequency |
+----------------------------------------+
|                                    128 |
+----------------------------------------+
</syntaxhighlight>
要增加该频率,请降低“innodb_purge_rseg_truncate_frequency”设置。例如,要使清除线程每 32 次调用清除一次查找撤消表空间,请将“innodb_purge_rseg_truncate_frequency”设置为 32.
<syntaxhighlight lang="mysql">
mysql> SET GLOBAL innodb_purge_rseg_truncate_frequency=32;
</syntaxhighlight>
当清除线程找到需要截断的撤消表空间时,清除线程以增加的频率返回,以快速清空并截断撤消表空间。
==== 截断撤消表空间文件的性能影响 ====
撤消表空间被截断时,撤消表空间中的回滚段将被停用。其他撤消表空间中的活动回滚段负责整个系统负载,这可能会导致性能轻微下降。性能下降的程度取决于许多因素:
* 撤消表空间的数量
* 撤消日志数
* 撤消表空间大小
* I/O 承载系统的速度
* 现有的长期事务
* System load
避免此潜在性能问题的最简单方法是'''增加撤消表空间的数量'''。
同样,在撤消表空间截断操作期间执行两个检查点操作。第一个检查点操作从缓冲池中删除旧的撤消表空间页。第二个检查点将新的撤消表空间的初始页面刷新到磁盘。在繁忙的系统上,如果要删除大量页面,则第一个检查点尤其会暂时影响系统性能。
==== 撤消表空间截断恢复 ====
撤消表空间截断操作会在服务器日志目录中创建一个临时“undo_space_number_trunc.log”文件。该日志目录由“innodb_log_group_home_dir”定义。如果在截断操作期间发生系统故障,则临时日志文件将允许启动过程标识正在被截断的撤消表空间并 continue 操作。
-->


== 临时表空间 ==
== 临时表空间 ==
在共享临时表空间中创建'''非压缩的,用户创建的临时表和磁盘内部临时表'''。 “'''innodb_temp_data_file_path'''”配置选项定义临时表空间数据文件的相对路径,名称,大小和属性。
* 如果没有为“innodb_temp_data_file_path”指定值,则默认行为是在“innodb_data_home_dir”目录中创建一个自动扩展的数据文件“ibtmp1”,该文件略大于 12MB。
*: [[File:InnoDB 临时表空间文件“ibtmp1”.png|500px]]
Note:<br/>
* 在 MySQL 5.6 中,未压缩的临时表在临时文件目录中的独占表空间中创建,或者如果禁用了“innodb_file_per_table”,则在数据目录的 InnoDB 系统表空间中创建。
* MySQL 5.7 中引入了共享临时表空间,从而消除了与为每个临时表创建和删除独占空间相关的性能成本。专用的临时表空间还意味着不再需要将临时表元数据保存到 InnoDB 系统表。
* 压缩的临时表是使用“ROW_FORMAT=COMPRESSED”属性创建的临时表,是在临时文件目录的独占表空间中创建的。【???】
* '''在正常关闭或初始化中止时,将删除临时表空间,并在每次启动服务器时重新创建该临时表空间'''。临时表空间在创建时会接收动态生成的空间 ID。如果无法创建临时表空间,则拒绝启动。如果服务器意外停止,则不会删除临时表空间。在这种情况下,数据库管理员可以手动删除临时表空间或重新启动服务器,这会自动删除并重新创建临时表空间。
* 临时表空间不能驻留在原始设备上。【?】
* “INFORMATION_SCHEMA.FILES”提供有关 InnoDB 临时表空间的元数据。发出与此查询类似的查询以查看临时表空间元数据:
*:<syntaxhighlight lang="mysql">
mysql> SELECT * FROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME='innodb_temporary'\G
</syntaxhighlight>
* “INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO”提供有关在 InnoDB 实例中当前处于活动状态的用户创建的临时表的元数据。
=== 管理临时表空间数据文件大小 ===
默认情况下,临时表空间数据文件是自动扩展的,并且会根据需要增加其大小以容纳磁盘上的临时表。例如,如果某个操作创建的临时表大小为 20MB,则临时表空间数据文件(在创建时默认为 12MB)会扩展大小以容纳该表。删除临时表后,可用空间可用于新的临时表,但'''数据文件将保持扩展大小'''。
# 要确定临时表空间数据文件是否正在自动扩展,请检查“innodb_temp_data_file_path”设置:
#: <syntaxhighlight lang="mysql">
mysql> SELECT @@innodb_temp_data_file_path;
+------------------------------+
| @@innodb_temp_data_file_path |
+------------------------------+
| ibtmp1:12M:autoextend        |
+------------------------------+
</syntaxhighlight>
# 要检查临时表空间数据文件的大小,请使用类似于以下查询的方法查询“INFORMATION_SCHEMA.FILES”表:
#: <syntaxhighlight lang="mysql">
mysql> SELECT FILE_NAME, TABLESPACE_NAME, ENGINE, INITIAL_SIZE, TOTAL_EXTENTS*EXTENT_SIZE AS TotalSizeBytes, DATA_FREE, MAXIMUM_SIZE
      FROM INFORMATION_SCHEMA.FILES
      WHERE TABLESPACE_NAME = 'innodb_temporary'\G
*************************** 1. row ***************************
      FILE_NAME: ./ibtmp1
TABLESPACE_NAME: innodb_temporary
        ENGINE: InnoDB
  INITIAL_SIZE: 12582912
TotalSizeBytes: 12582912
      DATA_FREE: 6291456
  MAXIMUM_SIZE: NULL
</syntaxhighlight>
#: TotalSizeBytes 值报告临时表空间数据文件的当前大小。
#* 或者,检查 os 上的临时表空间数据文件大小。
#*: 默认情况下,临时表空间数据文件位于“innodb_temp_data_file_path”配置选项定义的目录中。如果未明确为此选项指定值,则会在“innodb_data_home_dir”中创建一个名为“ibtmp1”的临时表空间数据文件,如果未指定,则默认为 MySQL 数据目录。
# 要回收临时表空间数据文件占用的磁盘空间,请'''重新启动 MySQL 服务器'''。重新启动服务器会根据“innodb_temp_data_file_path”定义的属性删除并重新创建临时表空间数据文件。
# 为防止临时数据文件变得太大,您可以配置“innodb_temp_data_file_path”选项以指定最大文件大小。例如:
#: <syntaxhighlight lang="mysql">
[mysqld]
innodb_temp_data_file_path=ibtmp1:12M:autoextend:max:500M
</syntaxhighlight>
#: 当数据文件达到最大大小时,查询将失败,并显示一个错误,指示 table 已满。配置“innodb_temp_data_file_path”需要重新启动服务器。
#* 或者,配置“default_tmp_storage_engine”和“internal_tmp_disk_storage_engine”选项,这两个选项定义了分别用于用户创建的和磁盘上的内部临时表的存储引擎【这两个选项默认都设置为 InnoDB】。
#*: MyISAM存储引擎为每个临时表使用一个单独的文件,该文件在删除临时表时将被删除。

2023年3月31日 (五) 23:23的最新版本


关于

tablespace:一个数据文件,可以保存一个或多个 InnoDB 表和关联的 索引 的数据。

  1. 系统表空间包含 InnoDB 数据字典,在 MySQL 5.6 之前,默认情况下保存所有其他 InnoDB 表。
  2. 在 MySQL 5.6 和更高版本中默认启用的“innodb_file_per_table”选项允许在自己的表空间中创建表。每表一文件(File-Per-Table)表空间支持以下功能,例如有效存储页外列,表压缩和可移动表空间。
  3. InnoDB 引入了 MySQL 5.7.6 中的常规表空间。常规表空间是使用“CREATE TABLESPACE”语法创建的共享表空间。它们可以在 MySQL 数据目录之外创建,能够容纳多个表,并支持所有行格式的表。

MySQL NDB Cluster 还将其表分组为表空间。【???】

什么是表空间

【转自CSDN博主「IT码客」:https://blog.csdn.net/u010647035/article/details/105009979】

概述

InnoDB 表空间(Tablespace)可以看做一个逻辑概念,InnoDB 把数据保存在表空间,本质上是一个或多个磁盘文件组成的虚拟文件系统。InnoDB 表空间不仅仅存储了表和索引,它还保存了回滚日志(redo log)、插入缓冲(insert buffer)、双写缓冲(doublewrite buffer)以及其他内部数据结构。


默认情况下InnoDB存储引擎有一个共享表空间“ibdata1”,即所有数据都放在这个表空间内。如果我们配置了参数“innodb_file_per_table”,则每张表内的数据可以单独放到一个表空间内。其对应的存储文件都放在“innodb_data_home_dir”指定的目录下。

InnoDB 系统表空间文件“ibdata1”.png InnoDB 独占表空间文件.png

(“ibdata1”在数据库第一次有实际内容时才生成?)

  • 当启用了“innodb_file_per_table”参数选项,需要注意的是,每张表的表空间内存放的只是数据、索引和插入缓冲,其它的数据,如撤销(Undo)信息、系统事务信息、二次写缓冲(double write buffer)等还是存放在原来的共享表空间内。这也就说明了另一个问题:即使在启用了参数“innodb_file_per_table”,共享表空间还是会不断地增加其大小。

InnoDB 逻辑存储结构

InnoDB 逻辑存储结构.png

从 InnoDB 逻辑存储结构来看,所有的数据都被逻辑的存放在一个空间中,这个空间就叫做表空间(tablespace)。表空间由:段(segment)、区(extent)、页(page)组成。

  1. (segment)
    段分为索引段(B+树的非叶子结点部分,即上图的“Non-leaf node segment”),数据段(B+树的叶子结点部分,即上图的“Leaf node segment”),回滚段(用于数据的回滚和多版本控制)等。一个段包含256个区(256M大小)。
    • 在InnoDB中,对段的管理都是有存储引擎自身完成的,DBA不能也没有必要对其进行空间。这和Oracle数据库中的自动段空间管理(ASSM)类似,从一定程度上简化了DBA对于段的管理
  2. (extent)
    区是页的集合,一个区包含64个连续的页,默认大小为 1MB (64*16K)。【不论页的大小怎么变化,区的大小总是为 1M】
    • 在默认情况下,InnoDB存储引擎页的大小为 16KB,即一个区一共有 64 个连续的页。
    • InnoDB 1.0.x 开始引入压缩页,即每个页的大小可以通过参数“KEY_BLOCK_SIZE”设置为 2K、4K、8K,因此每个区对应页的数量就应该为 512、256、128。
    • InnoDB 1.2.x 开始新增了参数“innodb_page_size”,通过该参数可以将默认页的大小设置为 4K、8K。但是页中的数据库不是压缩。这时区中页的数量同样也为 256、128。
    • 当启用参数“innodb_file_per_table”后,创建的表默认大小是 96KB:在每个段开始时,先用32个页大小的碎片页去存放数据,在使用完这些页之后才开始申请64个连续的页。【?】
      这样做的目的是:对于一些小表,或者是undo这类的段,可以在开始时申请较少的空间,节省磁盘容量的开销。
  3. (page)
    页是 InnoDB 管理的最小单位,常见的有“FSP_HDR”,“INODE”,“INDEX”等类型。所有页的结构都是一样的,分为“文件头”(前38字节),“页数据”和“文件尾”(后8字节)。页数据根据页的类型不同而不一样。
    每个空间都分为多个页,通常每页16 KiB。空间中的每个页面都分配有一个 32 位整数页码,通常称为“偏移量”(offset),它实际上只是页面与空间开头的偏移量(对于多文件空间,不一定是文件的偏移量)。因此,页面 0 位于文件偏移量 0,页面 1 位于文件偏移量 16384(1个文件16KB的偏移,即:16 x 1024 = 16384),依此类推。
    • (InnoDB 的数据限制为 64TiB,这实际上是每个空间的限制,这主要是由于页码是 32 位整数与默认页大小的组合: 2^32 x 16 KiB = 64 TiB )

关于“页”

InnoDB 页(page)结构.png

InnoDB 磁盘管理的最小单位。如图所示,每个page都有 38 个字节的 FIL header,以及 8 个字节的 FIL trailer(FIL 是 file 的简称)。FIL header 包含了一个表示 page type 的字段,这个字段用来确定这个 page 数据的结构。

FIL header 和 trailer 示意图如下所示:

InnoDB FIL header和trailer示意图.png

其中:

  • checksum: 4个字节32位checksum保存在header中。
  • Offset: 页面初始化后,页面编号就存储在header中。根据从文件中获得的偏移量检查从该字段读取的页码是否与应该匹配的页码相符,这有助于指示读取正确,并且此字段已初始化表示页面已初始化。
  • Previous/Next Page: 指向此页面类型的逻辑上一页和下一页的指针,被保存在header中。这允许建立页面的双向链接列表,并且它用于INDEX页面以及同一级别的所有页面。
  • page type: 页面类型存储在标题中。为了解析其余页面数据,这是必需的。页面被分配用于文件空间管理,范围管理,事务系统,数据字典,撤消日志,blob,当然还有索引(表数据)。
  • space ID: 保存在header中,space的32位整型唯一编号。
  • Old-style Checksum: 旧格式32位checksum被保存在header中,不过已经被废弃,这块空间被申明为一些指针。
  • LSN: 页的最后修改的64位日志序列号(LSN)存储在header中,而同一LSN的低32位存储在尾部中。

系统表空间

系统表空间是 InnoDB “数据字典”,“双写缓冲区”,“更改缓冲区”和“撤消日志”的存储区域。如果在系统表空间中创建表,而不是在“独占表空间”(File-Per-Table Tablespace)或“常规表空间”(General Tablespace)中创建表,则它也可能包含索引数据。


系统表空间可以具有一个或多个数据文件。默认情况下,在数据目录中创建一个名为“ibdata1”的单个系统表空间数据文件。系统表空间数据文件的大小和数量由“innodb_data_file_path”启动选项定义。

调整系统表空间的大小

增加系统表空间的大小:

  1. 最简单方法是将其配置为自动扩展。为此,请为“innodb_data_file_path”设置中的最后一个数据文件指定“autoextend”属性,然后重新启动服务器。
    例如:
    innodb_data_file_path=ibdata1:10M:autoextend
    
    指定“autoextend”属性后,数据文件会根据需要自动以 8MB 的增量增加大小。
    • “innodb_autoextend_increment”变量控制增量大小。
  2. 还可以通过添加另一个数据文件来增加系统表空间的大小。为此:
    1. 停止 MySQL 服务器。
    2. 如果“innodb_data_file_path”设置中的最后一个数据文件是使用“autoextend”属性定义的,请将其删除,然后修改“size”属性以反映当前数据文件的大小。要确定要指定的适当数据文件大小,请检查文件系统中的文件大小,并将该值四舍五入为最接近的 MB 值,其中 MB 等于 1024 x 1024。
    3. 将新的数据文件追加到“innodb_data_file_path”设置,可以选择指定“autoextend”属性。
      • 只能为“innodb_data_file_path”设置中的最后一个数据文件指定“autoextend”属性。
    4. 启动 MySQL 服务器。
    例如:
    innodb_data_home_dir =
    innodb_data_file_path = /ibdata/ibdata1:10M:autoextend
    
    假设数据文件随时间增长到 988MB。修改大小属性以反映当前数据文件大小之后,并指定新的 50MB 自动扩展数据文件后,这是innodb_data_file_path设置:
    innodb_data_home_dir =
    innodb_data_file_path = /ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend
    
    • 添加新数据文件时,请勿指定现有文件名。 InnoDB在启动服务器时创建并初始化新的数据文件。

NOTE:

  • 不能通过更改其大小属性来增加现有系统表空间数据文件的大小。例如,将 innodb_data_file_path 设置从 ibdata1:10M:autoextend 更改为 ibdata1:12M:autoextend 会在启动服务器时产生以下错误:
    [ERROR] [MY-012263] [InnoDB] The Auto-extending innodb_system
    data file './ibdata1' is of a different size 640 pages (rounded down to MB) than
    specified in the .cnf file: initial 768 pages, max 0 (relevant if non-zero) pages!
    
    该错误表明现有数据文件大小(以InnoDB页表示)与配置文件中指定的大小不同。如果遇到此错误,请还原以前的 innodb_data_file_path 设置,然后参考系统表空间大小调整说明。
    • InnoDB 页面大小由 innodb_page_size 变量定义。默认值为 16384 字节。


减小系统表空间的大小:

  1. 使用 mysqldump 转储所有 InnoDB 表,包括位于 mysql 模式中的 InnoDB 表。使用以下查询在 mysql 模式中标识 InnoDB 表:
    mysql> SELECT TABLE_NAME from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='mysql' and ENGINE='InnoDB';
    +---------------------------+
    | TABLE_NAME                |
    +---------------------------+
    | engine_cost               |
    | gtid_executed             |
    | help_category             |
    | help_keyword              |
    | help_relation             |
    | help_topic                |
    | innodb_index_stats        |
    | innodb_table_stats        |
    | plugin                    |
    | server_cost               |
    | servers                   |
    | slave_master_info         |
    | slave_relay_log_info      |
    | slave_worker_info         |
    | time_zone                 |
    | time_zone_leap_second     |
    | time_zone_name            |
    | time_zone_transition      |
    | time_zone_transition_type |
    +---------------------------+
    
  2. 停止服务器。
  3. 删除所有现有的表空间文件(*.ibd),包括“ibdata”和“ib_log”文件。【不要忘记删除 mysql 模式中的表的 *.ibd 文件】
  4. 删除 InnoDB 表的所有“.frm”文件。
  5. 为新系统表空间配置数据文件。【参见系统表空间数据文件配置】
  6. 重新启动服务器。
  7. 导入转储文件。

NOTE:

  • 如果您的数据库仅使用 InnoDB 引擎,则转储所有数据库,停止服务器,删除所有数据库和InnoDB日志文件,重新启动服务器以及导入转储文件可能更简单。


为避免使用较大的系统表空间,请考虑为数据使用“独占表空间”(File-Per-Table Tablespace)。

  • 【独占表空间是默认的表空间类型,在创建InnoDB表时隐式使用】。
  • 与系统表空间不同,截断或删除在独占表空间中创建的 table 后,磁盘空间会返回到 os。

对系统表空间使用原始磁盘分区【???】

您可以在InnoDB system tablespace中将原始磁盘分区用作数据文件。此技术可在 Windows 以及某些 Linux 和 Unix 系统上启用无缓冲的 I/O,而不会增加文件系统的开销。在有和没有原始分区的情况下执行测试,以验证此更改是否确实提高了系统性能。


使用原始磁盘分区时,请确保运行 MySQL 服务器的用户 ID 具有该分区的读写特权。例如,如果您以mysql用户身份运行服务器,则分区必须由mysql可读和可写。如果使用“--memlock”选项运行服务器,则服务器必须以root身份运行,因此该分区必须可由root读写。


在 Linux 和 Unix 系统上分配原始磁盘分区:

  1. 创建新数据文件时,请在“innodb_data_file_path”选项的数据文件大小后立即指定关键字“newraw”。分区必须至少与您指定的大小一样大。
    [mysqld]
    innodb_data_home_dir=
    innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw
    
  2. 重新启动服务器。 InnoDB 注意到“newraw”关键字并初始化新分区。但是,请不要创建或更改任何 InnoDB 表。否则,当您下次重新启动服务器时,InnoDB 重新初始化该分区,并且所做的更改将丢失。 (作为安全措施,InnoDB可以防止用户在指定带有“newraw”的任何分区时修改数据.)
  3. InnoDB 初始化新分区后,停止服务器,将数据文件规范中的“newraw”更改为“raw”:
    [mysqld]
    innodb_data_home_dir=
    innodb_data_file_path=/dev/hdd1:3Graw;/dev/hdd2:2Graw
    
  4. 重新启动服务器。 InnoDB 现在允许进行更改。

在 Windows 上分配原始磁盘分区:

在 Windows 系统上,适用于 Linux 和 Unix 系统的相同步骤和随附的准则适用于 Windows,但“innodb_data_file_path”设置略有不同。

  1. 创建新的数据文件时,请在“innodb_data_file_path”选项的数据文件大小后立即指定关键字“newraw”:
    [mysqld]
    innodb_data_home_dir=
    innodb_data_file_path=//./D::10Gnewraw
    
    • //./对应于用于访问物理驱动器的 Windows 语法\\.\。在上面的示例中,D:是分区的驱动器号。
  2. 重新启动服务器。 InnoDB 注意到“newraw”关键字并初始化新分区。
  3. InnoDB初始化新分区后,停止服务器,将数据文件规范中的“newraw”更改为“raw”:
    [mysqld]
    innodb_data_home_dir=
    innodb_data_file_path=//./D::10Graw
    
  4. 重新启动服务器。 InnoDB 现在允许进行更改。

独占(File-Per-Table)表空间

独占表空间包含单个 InnoDB 表的数据和索引,并存储在文件系统中自己的数据文件中。

独占表空间配置

InnoDB 默认情况下在独占表空间中创建表。此行为由“innodb_file_per_table”变量控制。【禁用“innodb_file_per_table”会导致 InnoDB 在系统表空间中创建表】


“innodb_file_per_table”设置可以在选项文件中指定,也可以在运行时使用“SET GLOBAL”语句进行配置(需要足够的特权来设置全局系统变量)。

  1. 选项文件中指定:
    [mysqld]
    innodb_file_per_table=ON
    
  2. 在运行时使用“SET GLOBAL”:
    mysql> SET GLOBAL innodb_file_per_table=ON;
    


NOTE: 对于启用了“innodb_file_per_table”的参数选项,需要注意的是 ,每张表的表空间内存放的只是数据、索引和插入缓冲 ,其他类的数据,如撤销(Undo)信息、系统事务信息、 二次写缓冲 (double write buffer ) 等还是存放在原来的共享表空间内。这也就说明了另一个问题:即使在启用了参数innodb_file_per_table之后,共享表空间还是会不断地增加其大小

独占表空间数据文件

在 MySQL 数据目录下的架构目录中的“.idb”数据文件中,创建了独占表空间。


例如,表 test.t1 的数据文件是在 MySQL 数据目录下的 test 目录中创建的:

mysql> USE test;

mysql> CREATE TABLE t1 (
   id INT PRIMARY KEY AUTO_INCREMENT,
   name VARCHAR(100)
 ) ENGINE = InnoDB;

shell> cd /path/to/mysql/data/test
shell> ls
t1.ibd
  • 可以使用“CREATE TABLE”语句的“DATA DIRECTORY”子句在数据目录外部隐式创建独占表空间数据文件。

独占表空间的优势

与共享表空间相比,独占表空间具有以下优点:【共享表空间:系统表空间或常规表空间】

  1. 截断或删除独占表空间中创建的表后,磁盘空间将返回 os
    截断或删除存储在共享表空间中的表会在共享表空间数据文件中创建可用空间,该可用空间仅可用于 InnoDB 数据。换句话说,在表被截断或删除后,共享表空间数据文件的大小不会缩小
  2. 对驻留在共享表空间中的表进行表复制“ALTER TABLE”操作可以增加表空间占用的磁盘空间量。此类操作可能需要与表中的数据加索引一样多的额外空间。该空间不会像每个表文件表空间那样释放回 os。
  3. 在独占表空间中的表上执行时,“TRUNCATE TABLE”性能更好
  4. 可以在单独的存储设备上创建独占表空间数据文件,以进行 I/O 优化,空间管理或备份。
  5. 可以从另一个 MySQL 实例导入一个位于独占表空间中的表
  6. 在独占表空间中创建的表使用 Barracuda 文件格式。Barracuda 文件格式(梭鱼文件格式???)启用与“DYNAMIC”和“COMPRESSED”行格式关联的功能。
  7. 当发生数据损坏,备份或二进制日志不可用或无法重新启动 MySQL 服务器实例时,存储在独占表空间数据文件中的表可以节省时间并提高成功恢复的机会
  8. 您可以使用 MySQL Enterprise Backup 快速备份或还原在独占表空间中创建的表,而不会中断其他 InnoDB 表的使用。这对于具有不同备份计划的表或需要较少备份的表很有用。
  9. 独占表空间允许通过监视表空间数据文件的大小来监视文件系统上的表大小。
  10. 当“innodb_flush_method”设置为“O_DIRECT”时,常见的 Linux 文件系统不允许并发写入单个文件,例如共享表空间数据文件。结果,当结合使用独占表空间和该设置时,可能会提高性能。
  11. 共享表空间中的表的大小受到 64TB 表空间大小限制的限制。相比之下,独占表空间都有 64TB 的大小限制,这为单个表的大小增加提供了足够的空间。

独占表空间的缺点

与共享表空间相比,独占表空间具有以下缺点:

  1. 使用独占表空间,每个表可能有未使用的空间,只能由同一表的行使用,如果管理不当,则会浪费空间。
  2. fsync 操作是针对每个表的多个文件而不是单个共享表空间的数据文件执行的。由于 fsync 操作是针对每个文件的,因此无法合并多个表的写操作,这可能导致 fsync 操作的总数更高。【???】
  3. mysqld 必须为独占表空间保留一个打开的文件句柄,如果独占表空间中有许多表,则这可能会影响性能。
  4. 每个表都有其自己的数据文件时,需要更多的文件描述符。
  5. 可能存在更多碎片,这可能会阻碍“DROP TABLE”和表扫描性能。但是,如果管理碎片,则独占表空间可以提高这些操作的性能。
  6. 删除驻留在独占表空间中的表时,将扫描缓冲池,对于大型缓冲池可能要花费几秒钟。使用广泛的内部锁定执行扫描,这可能会延迟其他操作。
  7. “innodb_autoextend_increment”变量定义用于在自动扩展共享表空间文件变满时扩展其大小的增量大小,该变量不适用于独占表空间文件,无论“innodb_autoextend_increment”设置如何,该文件都将自动扩展。初始的独占表空间的 extensions 很少,之后 extensions 以 4MB 为增量。

常规表空间

常规表空间是使用“CREATE TABLESPACE”语法创建的共享 InnoDB 表空间

常规表空间功能

常规表空间功能提供以下功能:

  1. 类似于系统表空间,常规表空间是共享表空间,可以存储多个表的数据
  2. 常规表空间比独占表空间具有潜在的内存优势。服务器在表空间的生存期内将表空间元数据保留在内存中。与独占表空间中的相同数量的表相比,较少的常规表空间中的多个表为表空间元数据消耗的内存更少。
  3. 常规表空间数据文件可以放置在相对于 MySQL 数据目录或独立于 MySQL 数据目录的目录中,这为您提供了独占表空间的许多数据文件和存储管理功能。与每表文件表空间一样,将数据文件放置在 MySQL 数据目录之外的功能使您可以分别管理关键表的性能,为特定表设置 RAID 或 DRBD 或将表绑定到特定磁盘。【?】
  4. 常规表空间支持 Antelope 和 Barracuda 文件格式【???】,因此支持所有表行格式和相关功能。支持两种文件格式,常规表空间不依赖于“innodb_file_format”或“innodb_file_per_table”设置,这些变量也不影响常规表空间。
  5. “TABLESPACE”选项可以与“CREATE TABLE”一起使用,以在常规表空间,独占表空间或系统表空间中创建表。
  6. “TABLESPACE”选项可与“ALTER TABLE”一起使用,以在常规表空间,独占表空间和系统表空间之间移动表。以前,不可能将表从每个表文件表空间移至系统表空间。使用常规表空间功能,您现在可以这样做。

创建常规表空间

常规表空间是使用“CREATE TABLESPACE”语法创建的。

CREATE TABLESPACE tablespace_name
    ADD DATAFILE 'file_name'
    [FILE_BLOCK_SIZE = value]
        [ENGINE [=] engine_name]
  • 常规表空间可以在数据目录中或在其外部创建。为避免与隐式创建的独占表空间冲突,不支持在数据目录下的子目录中创建常规表空间
    • 在数据目录之外创建常规表空间时,该目录必须在创建表空间之前存在。
  • 在 MySQL 数据目录之外创建常规表空间时,会在 MySQL 数据目录中创建“.isl”文件。【?】


示例:

  1. 在数据目录中创建常规表空间:
    mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
    
  2. 在数据目录之外的目录中创建常规表空间:
    mysql> CREATE TABLESPACE `ts1` ADD DATAFILE '/my/tablespace/directory/ts1.ibd' Engine=InnoDB;
    
    • 您可以指定相对于数据目录的路径,只要表空间目录不在数据目录下即可。在此示例中,my_tablespace 目录与数据目录处于同一级别:
      mysql> CREATE TABLESPACE `ts1` ADD DATAFILE '../my_tablespace/ts1.ibd' Engine=InnoDB;
      
  • “ENGINE = InnoDB”子句必须定义为“CREATE TABLESPACE”语句的一部分,或者 InnoDB 必须定义为默认存储引擎(default_storage_engine=InnoDB)。

将表添加到常规表空间

创建 InnoDB 常规表空间后,可以使用“CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_name”或“ALTER TABLE tbl_name TABLESPACE [=] tablespace_name”将表添加到表空间。


示例:

  1. CREATE TABLE:
    mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1;
    
  2. ALTER TABLE:
    mysql> ALTER TABLE t2 TABLESPACE ts1;
    
  • 在 MySQL 5.7.24 中已弃用了将表分区放置在共享表空间中的支持,并且在将来的 MySQL 版本中将删除该支持。【?】

常规表空间行格式支持【????????】

使用“ALTER TABLE”在表空间之间移动表

您可以将“ALTER TABLE”与“TABLESPACE”选项一起使用,以将表移至现有的常规表空间,新的独占表空间或系统表空间。

  1. 要将表从独占表空间或系统表空间移至常规表空间,请指定常规表空间的名称。
    • 常规表空间必须存在。
    ALTER TABLE tbl_name TABLESPACE [=] tablespace_name;
    
  2. 要将表从常规表空间或独占表空间移至系统表空间,请指定“innodb_system”作为表空间名称。
    ALTER TABLE tbl_name TABLESPACE [=] innodb_system;
    
  3. 要将表从系统表空间或常规表空间移至独占表空间,请指定“innodb_file_per_table”作为表空间名称。
    ALTER TABLE tbl_name TABLESPACE [=] innodb_file_per_table;
    


NOTE:

  • “ALTER TABLE ... TABLESPACE”操作始终会导致整个表的重建,即使“TABLESPACE”属性与其之前的值相比也没有变化。
  • “ALTER TABLE ... TABLESPACE”语法不支持将表从临时表空间移动到持久表空间
  • “DATA DIRECTORY”子句与“CREATE TABLE ... TABLESPACE=innodb_file_per_table”一起允许,但不支持与“TABLESPACE”选项结合使用。
  • 从加密表空间中移动表时有限制。

删除常规表空间

“DROP TABLESPACE”语句用于删除 InnoDB 常规表空间。

  • “DROP TABLESPACE”操作之前,必须从表空间中删除所有表。如果表空间不为空,则返回错误。


使用类似于以下内容的查询来标识常规表空间中的表。

mysql> SELECT a.NAME AS space_name, b.NAME AS table_name 
     FROM INFORMATION_SCHEMA.INNODB_TABLESPACES a,
       INFORMATION_SCHEMA.INNODB_TABLES b 
     WHERE a.SPACE=b.SPACE AND a.NAME LIKE 'ts1';
+------------+------------+
| space_name | table_name |
+------------+------------+
| ts1        | test/t1    |
| ts1        | test/t2    |
| ts1        | test/t3    |
+------------+------------+


NOTE:

  • 如果对空的通用表空间的“DROP TABLESPACE”操作返回错误,则该表空间可能包含由服务器 Export 中断的“ALTER TABLE”操作留下的孤立临时表或中间表。
  • 删除表空间中的最后一个表时,一般的 InnoDB表空间不会自动删除。必须使用“DROP TABLESPACE tablespace_name”明确删除表空间
  • 常规表空间不属于任何特定数据库。 “DROP DATABASE”操作可以删除属于常规表空间的表,但是即使“DROP DATABASE”操作删除了属于该表空间的所有表,也不能删除该表空间。必须使用“DROP TABLESPACE tablespace_name”显式删除常规表空间。
  • 与系统表空间类似,截断或删除存储在通用表空间中的表会在通用表空间“.ibd”数据文件内部内部创建可用空间,该可用空间仅可用于新的 InnoDB 数据。在“DROP TABLE”操作期间删除每表文件表空间时,不会将空间释放回 os
  • “tablespace_name”是 MySQL 中区分大小写的标识符。

常规表空间限制

  • 生成的表空间或现有表空间不能更改为常规表空间
  • 不支持创建临时通用表空间。
  • 常规表空间不支持临时表
  • 通用表空间中存储的表只能在支持通用表空间的 MySQL 版本中打开。
  • 与系统表空间类似,截断或删除存储在通用表空间中的表会在通用表空间“.ibd”数据文件内部内部创建可用空间,该可用空间仅可用于新的 InnoDB 数据。空间不会像独占表空间那样释放回 os。
    此外,驻留在共享表空间(通用表空间或系统表空间)中的表的表复制“ALTER TABLE”操作可以增加表空间使用的空间量。此类操作需要与表中的数据以及索引一样多的额外空间。表复制“ALTER TABLE”操作所需的额外空间不会像每个表文件表空间那样释放回 os。
  • 属于常规表空间的表不支持“ALTER TABLE ... DISCARD TABLESPACE”和“ALTER TABLE ...IMPORT TABLESPACE”。
  • 在源和副本位于同一主机上的复制环境中,不支持“ADD DATAFILE”子句,因为这会导致源和副本在同一位置创建相同名称的表空间。【?】
  • 在 MySQL 5.7.24 中已弃用了将表分区放置在常规表空间中的支持,并且在将来的 MySQL 版本中将删除该支持。【?】

撤消(Undo)表空间【?????】

撤消表空间包含撤消日志,撤消日志是撤消日志记录的集合,其中包含有关如何通过事务撤消对聚集索引记录的最新更改的信息。

  • 撤消日志存在于“撤消日志段”中,撤消日志段包含在“回滚段”中。“innodb_rollback_segments”变量定义分配给每个撤消表空间的回滚段的数量。


Undo logs 可以存储在一个或多个 undo tablespaces 中,而不是 system tablespace 中。此布局不同于 undo logs 位于 system tablespace 中的默认配置。撤消日志的 I/O 模式使撤消表空间成为 SSD 存储的理想候选者,同时将系统表空间保留在硬盘存储上。


InnoDB 使用的撤消表空间的数量由“innodb_undo_tablespaces”配置选项控制。仅在初始化 MySQL 实例时才能配置此选项。此后无法更改。【innodb_undo_tablespaces 配置选项已弃用,在以后的版本中将被删除。】


撤消表空间和这些表空间中的单个 segments 不能删除。但是,存储在撤消表空间中的撤消日志可以被截断。

临时表空间

在共享临时表空间中创建非压缩的,用户创建的临时表和磁盘内部临时表。 “innodb_temp_data_file_path”配置选项定义临时表空间数据文件的相对路径,名称,大小和属性。

  • 如果没有为“innodb_temp_data_file_path”指定值,则默认行为是在“innodb_data_home_dir”目录中创建一个自动扩展的数据文件“ibtmp1”,该文件略大于 12MB。
    InnoDB 临时表空间文件“ibtmp1”.png


Note:

  • 在 MySQL 5.6 中,未压缩的临时表在临时文件目录中的独占表空间中创建,或者如果禁用了“innodb_file_per_table”,则在数据目录的 InnoDB 系统表空间中创建。
  • MySQL 5.7 中引入了共享临时表空间,从而消除了与为每个临时表创建和删除独占空间相关的性能成本。专用的临时表空间还意味着不再需要将临时表元数据保存到 InnoDB 系统表。


  • 压缩的临时表是使用“ROW_FORMAT=COMPRESSED”属性创建的临时表,是在临时文件目录的独占表空间中创建的。【???】
  • 在正常关闭或初始化中止时,将删除临时表空间,并在每次启动服务器时重新创建该临时表空间。临时表空间在创建时会接收动态生成的空间 ID。如果无法创建临时表空间,则拒绝启动。如果服务器意外停止,则不会删除临时表空间。在这种情况下,数据库管理员可以手动删除临时表空间或重新启动服务器,这会自动删除并重新创建临时表空间。
  • 临时表空间不能驻留在原始设备上。【?】
  • “INFORMATION_SCHEMA.FILES”提供有关 InnoDB 临时表空间的元数据。发出与此查询类似的查询以查看临时表空间元数据:
    mysql> SELECT * FROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME='innodb_temporary'\G
    
  • “INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO”提供有关在 InnoDB 实例中当前处于活动状态的用户创建的临时表的元数据。

管理临时表空间数据文件大小

默认情况下,临时表空间数据文件是自动扩展的,并且会根据需要增加其大小以容纳磁盘上的临时表。例如,如果某个操作创建的临时表大小为 20MB,则临时表空间数据文件(在创建时默认为 12MB)会扩展大小以容纳该表。删除临时表后,可用空间可用于新的临时表,但数据文件将保持扩展大小

  1. 要确定临时表空间数据文件是否正在自动扩展,请检查“innodb_temp_data_file_path”设置:
    mysql> SELECT @@innodb_temp_data_file_path;
    +------------------------------+
    | @@innodb_temp_data_file_path |
    +------------------------------+
    | ibtmp1:12M:autoextend        |
    +------------------------------+
    
  2. 要检查临时表空间数据文件的大小,请使用类似于以下查询的方法查询“INFORMATION_SCHEMA.FILES”表:
    mysql> SELECT FILE_NAME, TABLESPACE_NAME, ENGINE, INITIAL_SIZE, TOTAL_EXTENTS*EXTENT_SIZE AS TotalSizeBytes, DATA_FREE, MAXIMUM_SIZE 
           FROM INFORMATION_SCHEMA.FILES
           WHERE TABLESPACE_NAME = 'innodb_temporary'\G
    *************************** 1. row ***************************
          FILE_NAME: ./ibtmp1
    TABLESPACE_NAME: innodb_temporary
             ENGINE: InnoDB
       INITIAL_SIZE: 12582912
     TotalSizeBytes: 12582912
          DATA_FREE: 6291456
       MAXIMUM_SIZE: NULL
    
    TotalSizeBytes 值报告临时表空间数据文件的当前大小。
    • 或者,检查 os 上的临时表空间数据文件大小。
      默认情况下,临时表空间数据文件位于“innodb_temp_data_file_path”配置选项定义的目录中。如果未明确为此选项指定值,则会在“innodb_data_home_dir”中创建一个名为“ibtmp1”的临时表空间数据文件,如果未指定,则默认为 MySQL 数据目录。
  3. 要回收临时表空间数据文件占用的磁盘空间,请重新启动 MySQL 服务器。重新启动服务器会根据“innodb_temp_data_file_path”定义的属性删除并重新创建临时表空间数据文件。
  4. 为防止临时数据文件变得太大,您可以配置“innodb_temp_data_file_path”选项以指定最大文件大小。例如:
    [mysqld]
    innodb_temp_data_file_path=ibtmp1:12M:autoextend:max:500M
    
    当数据文件达到最大大小时,查询将失败,并显示一个错误,指示 table 已满。配置“innodb_temp_data_file_path”需要重新启动服务器。
    • 或者,配置“default_tmp_storage_engine”和“internal_tmp_disk_storage_engine”选项,这两个选项定义了分别用于用户创建的和磁盘上的内部临时表的存储引擎【这两个选项默认都设置为 InnoDB】。
      MyISAM存储引擎为每个临时表使用一个单独的文件,该文件在删除临时表时将被删除。