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

来自Wikioe
跳到导航 跳到搜索
第61行: 第61行:




系统表空间可以具有一个或多个数据文件。默认情况下,在数据目录中创建一个名为“ibdata1”的单个系统表空间数据文件。系统表空间数据文件的大小和数量由“innodb_data_file_path”启动选项定义。
系统表空间可以具有一个或多个数据文件。默认情况下,在数据目录中创建一个名为“'''ibdata1'''”的单个系统表空间数据文件。系统表空间数据文件的大小和数量由“innodb_data_file_path”启动选项定义。
 
=== 调整系统表空间的大小 ===
增加系统表空间的大小:<br/>
# 最简单方法是将其配置为自动扩展。为此,请为“'''innodb_data_file_path'''”设置中的最后一个数据文件指定“'''autoextend'''”属性,然后重新启动服务器。
#: 例如:
#: <syntaxhighlight lang="mysql">
innodb_data_file_path=ibdata1:10M:autoextend
</syntaxhighlight>
#: 指定“autoextend”属性后,数据文件会根据需要自动以 '''8MB''' 的增量增加大小。
#* “innodb_autoextend_increment”变量控制增量大小。
# 还可以通过添加另一个数据文件来增加系统表空间的大小。为此:
## 停止 MySQL 服务器。
## 如果“innodb_data_file_path”设置中的最后一个数据文件是使用“autoextend”属性定义的,请将其删除,然后修改“size”属性以反映当前数据文件的大小。要确定要指定的适当数据文件大小,请检查文件系统中的文件大小,并将该值四舍五入为最接近的 MB 值,其中 MB 等于 1024 x 1024。
## 将新的数据文件追加到“innodb_data_file_path”设置,可以选择指定“autoextend”属性。
##* 只能为“innodb_data_file_path”设置中的最后一个数据文件指定“autoextend”属性。
## 启动 MySQL 服务器。
#: 例如:
#: <syntaxhighlight lang="mysql">
innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:10M:autoextend
</syntaxhighlight>
#: 假设数据文件随时间增长到 988MB。修改大小属性以反映当前数据文件大小之后,并指定新的 50MB 自动扩展数据文件后,这是innodb_data_file_path设置:
#: <syntaxhighlight lang="mysql">
innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend
</syntaxhighlight>
#* 添加新数据文件时,请勿指定现有文件名。 InnoDB在启动服务器时创建并初始化新的数据文件。
 
NOTE:
* 不能通过更改其大小属性来增加现有系统表空间数据文件的大小。例如,将 innodb_data_file_path 设置从 ibdata1:10M:autoextend 更改为 ibdata1:12M:autoextend 会在启动服务器时产生以下错误:
*: <syntaxhighlight lang="mysql">
[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!
</syntaxhighlight>
*: 该错误表明现有数据文件大小(以InnoDB页表示)与配置文件中指定的大小不同。如果遇到此错误,请还原以前的 innodb_data_file_path 设置,然后参考系统表空间大小调整说明。
** InnoDB 页面大小由 innodb_page_size 变量定义。默认值为 16384 字节。
 
 
 
减小系统表空间的大小:<br/>
# 使用 mysqldump 转储所有 InnoDB 表,包括位于 mysql 模式中的 InnoDB 表。使用以下查询在 mysql 模式中标识 InnoDB 表:
#: <syntaxhighlight lang="mysql">
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 |
+---------------------------+
</syntaxhighlight>
# 停止服务器。
# 删除所有现有的表空间文件(*.ibd),包括“ibdata”和“ib_log”文件。【不要忘记删除 mysql 模式中的表的 *.ibd 文件】
# 删除 InnoDB 表的所有“.frm”文件。
# 为新系统表空间配置数据文件。【参见系统表空间数据文件配置】
# 重新启动服务器。
# 导入转储文件。
 
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 系统上分配原始磁盘分区: ====
# 创建新数据文件时,请在“innodb_data_file_path”选项的数据文件大小后立即指定关键字“newraw”。分区必须至少与您指定的大小一样大。
#: <syntaxhighlight lang="mysql">
[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw
</syntaxhighlight>
# 重新启动服务器。 InnoDB 注意到“newraw”关键字并初始化新分区。但是,请不要创建或更改任何 InnoDB 表。否则,当您下次重新启动服务器时,InnoDB 重新初始化该分区,并且所做的更改将丢失。 (作为安全措施,InnoDB可以防止用户在指定带有“newraw”的任何分区时修改数据.)
# InnoDB 初始化新分区后,停止服务器,将数据文件规范中的“newraw”更改为“raw”:
#: <syntaxhighlight lang="mysql">
[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/hdd1:3Graw;/dev/hdd2:2Graw
</syntaxhighlight>
# 重新启动服务器。 InnoDB 现在允许进行更改。
 
==== 在 Windows 上分配原始磁盘分区: ====
在 Windows 系统上,适用于 Linux 和 Unix 系统的相同步骤和随附的准则适用于 Windows,但“innodb_data_file_path”设置略有不同。
 
# 创建新的数据文件时,请在“innodb_data_file_path”选项的数据文件大小后立即指定关键字“newraw”:
#:<syntaxhighlight lang="mysql">
[mysqld]
innodb_data_home_dir=
innodb_data_file_path=//./D::10Gnewraw
</syntaxhighlight>
#* //./对应于用于访问物理驱动器的 Windows 语法\\.\。在上面的示例中,D:是分区的驱动器号。
# 重新启动服务器。 InnoDB 注意到“newraw”关键字并初始化新分区。
# InnoDB初始化新分区后,停止服务器,将数据文件规范中的“newraw”更改为“raw”:
#:<syntaxhighlight lang="mysql">
[mysqld]
innodb_data_home_dir=
innodb_data_file_path=//./D::10Graw
</syntaxhighlight>
# 重新启动服务器。 InnoDB 现在允许进行更改。


== 每表一文件(File-Per-Table)表空间 ==
== 每表一文件(File-Per-Table)表空间 ==

2021年4月18日 (日) 17:07的版本


关于

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)
    段分为索引段数据段回滚段等。其中:
  2. 索引段就是非叶子结点部分,
  3. 而数据段就是叶子结点部分,
  4. 回滚段用于数据的回滚和多版本控制。
    一个段包含256个区(256M大小)。
  5. (extent)
    区是页的集合,一个区包含64个连续的页,默认大小为 1MB (64*16K)。
  6. (page)
    页是 InnoDB 管理的最小单位,常见的有“FSP_HDR”,“INODE”,“INDEX”等类型。所有页的结构都是一样的,分为“文件头”(前38字节),“页数据”和“文件尾”(后8字节)。页数据根据页的类型不同而不一样。
    每个空间都分为多个页,通常每页16 KiB。空间中的每个页面都分配有一个32位整数页码,通常称为“偏移量”(offset),它实际上只是页面与空间开头的偏移量(对于多文件空间,不一定是文件的偏移量)。因此,页面 0 位于文件偏移量 0,页面 1 位于文件偏移量 16384,依此类推。
    • (InnoDB 的数据限制为64TiB,这实际上是每个空间的限制,这主要是由于页码是32位整数与默认页大小的组合: 2^32 x 16 KiB = 64 TiB )


关于“页”:

InnoDB 页(page)结构.png

如图所示,每个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)表空间

常规表空间

撤消(Undo)表空间

临时表空间