暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

InnoDB 磁盘结构:常规表空间

我与风来 2021-05-26
711

general tablespace,翻译为常规表空间。该表空间属于共享的 InnoDB 表空间,可以使用 CREATE TABLESPACE
语法创建。后续将主要介绍常规表空间的功能和特性。

常规表空间的功能

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

  • 与系统表空间类似,常规表空间也是能够存储多个表的数据的共享表空间

  • 常规表空间相比file-per-table
    表空间具有潜在的内存优势。服务器将表空间生命周期内的元数据保存在内存中。与 file-per-table
    表空间中单独文件中相同数据的表相比,在常规表空间中的多个表的元数据内存占用更少。

  • 常规表空间数据文件可以放置在与 MySQL 数据目录相对或独立的目录,这为你提供了与 file-per-table
    表空间相似的多数据文件和存储管理功能。与 file-per-table
    一样,将数据文件放置在 Mysql 数据目录之外的能力允许您分别管理关键表的性能、为特定表设置 RAID(磁盘陈列,独立磁盘构成的具有冗余能力的陈列) 或 DRBD(分布式复制块设备,实现活动节点存储数据更新后自动复制到备用节点相应存储位置的软件) ,或将表绑定到特定磁盘。

  • 常规表空间支持所有表行格式和相关功能。

  • TABLESPACE 选项能够与 CREATE TABLE
    一起使用,以在常规表空间、file-per-table
    表空间或系统表空间中创建表。

  • TABLESPACE 选项可以与 ALTER TABLE
    一起使用,在常规表空间、file-per-table
    表空间和系统表空间之间改变表。

创建一个常规表空间

使用 CRATE TABLESPACE
语法创建常规表空间。

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

可以在数据目录中或数据目录外部创建常规表空间。为避免与按表隐式创建的 file-per-table
表空间冲突,不支持在数据目录下的子目录中创建常规表空间。在数据目录外创建常规表空间时,该目录必须存在,并且在创建表空间之前,InnoDB 必须知道该目录。要使 InnoDB 知道一个未知目录,请将该目录添加到 innoDB_directories
参数值中。innoDB_directories
是一个只读启动选项。配置它需要重新启动服务器。

例如:
在数据目录创建一个常规表空间:

CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;

你能够在数据目录下找到创建的数据文件 ts1.ibd,或者使用下列语句:

CREATE TABLESPACE `ts1` Engine=InnoDB;

如果你已经执行过第一条语句,在执行第二条语句时,你需要更换表空间的名称,将 ts1 改为 ts2 即可。但在数据目录下,我们并未找到 ts2.ibd。如果你注意到了这两个语句的不同,应该能明白问题在哪里。

从 MySQL 8.0.14 开始,ADD DATAFILE 子句是可选的,在此之前是必需的。如果在创建表空间时未指定 ADD DATAFILE 子句,则会隐式创建具有唯一文件名的表空间数据文件。唯一的文件名是一个 128 位 UUID,格式为五组十六进制数,用破折号分隔(aaaaaaaa-bbbb-cccc-dddd-eeeeee)。常规表空间数据文件包括.ibd文件扩展名。在复制环境中,在源上创建的数据文件名与在副本上创建的数据文件名不同。这下结合数据目录中,文件的创建时间,你应该很容易找到这个数据文件。

在数据目录外部的数据目录创建常规表空间:

CREATE TABLESPACE `ts3` ADD DATAFILE 'D:/mysql-8.0.22-winx64/generaltablespace/ts3.ibd' Engine=InnoDB;

不过,执行该语句会得到一个 The DATAFILE location must be in a known directory.
。前面提到过必须要使 InnoDB 知道该目录,修改 mysql 配置文件,新增以下配置:

innodb_directories="D:\mysql-8.0.22-winx64\generaltablespace"

然后重新执行创建语句即可。除了绝对路径,也可使用相对于数据目录的相对路径创建常规表空间的数据文件:

CREATE TABLESPACE `ts4` ADD DATAFILE '../generaltablespace/ts4.ibd' Engine=InnoDB;

添加表到常规表空间

在创建了常规表空间之后,可以通过 CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_name
或者 ALTER TABLE tbl_name TABLESPACE [=] tablespace_name
语句将表添加到常规表空间:

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

注意:在 MySQL5.7.24 中,不赞成将表分区添加到共享表空间,而在 MySQL8.0.13 中删除了对表分区的支持。共享表空间包括 InnoDB 系统表空间和常规表空间。

常规表空间的行格式支持

常规表空间支持所有表行格式(冗余、紧凑、动态、压缩),但需要注意的是,由于物理页大小不同,压缩表和未压缩表不能共存于同一个常规表空间中。

对于包含压缩表的常规表空间(ROW_FORMAT=COMPRESSED
),必须指定 FILE_BLOCK_SIZE
选项,并且 FILE_BLOCK_SIZE
值必须是相对于 innodb_page_size
值的有效压缩页大小。此外,压缩表的物理页大小(KEY_BLOCK_SIZE
)必须等于 FILE_BLOCK_SIZE/1024
。例如,如果 innodb_page_size=16KB
FILE_BLOCK_size=8K
,则表的 KEY_BLOCK_SIZE 必须为8。

有关更详细的 innodb 页面大小、文件块大小和键块大小组合可以去这块的文档查看。FILE_BLOCK_SIZE  值也可以以字节为单位指定。要确定给定文件块大小的有效键块大小值,请将文件块大小值除以1024。32K和64K 的 innodb 页面大小不支持表压缩。

此示例演示如何创建常规表空间和添加压缩表。该示例假定默认的innodb页大小为16KB。文件块大小为8192,要求压缩表的键块大小为8。

CREATE TABLESPACE `ts5` ADD DATAFILE 'ts5.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;

CREATE TABLE t4 (c1 INT PRIMARY KEYTABLESPACE ts5 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;

如果在创建常规表空间时未指定 FILE_BLOCK_SIZE
,则 FILE_BLOCK_SIZE
默认为 innodb_page_size
。当 FILE_BLOCK_SIZE
等于 innodb_page_size
时,表空间可能只包含未压缩行格式的表(紧凑、冗余和动态行格式)。

使用 ALTER TABLE 在表空间间移动表

要将表从 file-per-table
表空间或从系统表空间移动到常规表空间,请指定常规表空间的名称。常规表空间必须存在。

ALTER TABLE tbl_name TABLESPACE [=] tablespace_name;

ALTER TABLE ... TABLESPACE
操作会导致完整的表重建,即使表空间属性没有改变它以前的值。

ALTER TABLE ... TABLESPACE
语法不支持将表从临时表空间移动到持久表空间。

CREATE TABLE ... TABLESPACE=innodb_file_per_table
允许 DATA DIRECTORY
子句,但不支持与 TABLESPACE 选项结合使用。从 MySQL8.0.21 开始,数据目录子句中指定的目录必须为 InnoDB 所知。有关详细信息,请参阅使用数据目录子句。

从加密的表空间移动表时会受到限制。加密仅支持 file-per-table
表空间、常规表空间和 mysql 系统表空间,InnoDB 系统表空间不支持加密。

重命名表空间

使用 ALTER TABLESPACE ... RENAME TO
语法重命名常规表空间。

ALTER TABLESPACE s1 RENAME TO s2;

删除常规表空间

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

在执行 DROP 表空间操作之前,必须从表空间中删除所有表。如果表空间不是空的,DROP TABLESPACE 将返回一个错误。

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

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';

当删除表空间中的最后一个表时,常规的 InnoDB 表空间不会自动删除。必须使用 DROP tablespace tablespace_name
显式删除表空间。

常规表空间不属于任何特定的数据库。DROP DATABASE
操作可以删除属于常规表空间的表,但不能删除该表空间,即使 DROP DATABASE 操作删除属于该表空间的所有表也是如此。

与系统表空间类似,截断或删除存储在常规表空间中的表会在 tablespace.ibd
数据文件内部创建可用空间,该文件只能用于新的 InnoDB 数据。空间不会像在删除表操作期间删除 file-per-table
表空间时那样释放回操作系统。

常规表空间限制

  • 不能将生成的或现有的表空间更改为常规表空间。

  • 不支持创建临时常规表空间。

  • 常规表空间不支持临时表。

  • 与系统表空间类似,截断或删除存储在常规表空间中的表会在 tablespace.ibd 数据文件内部创建可用空间,该文件只能用于新的InnoDB数据。空间不会释放回操作系统。

  • 此外,对驻留在共享表空间(常规表空间或系统表空间)中的表执行表的复制 ALTER table
    操作会增加表空间使用的空间量。这样的操作需要与表中的数据加索引一样多的额外空间。表复制 ALTER table 操作所需的额外空间不会像 file-per-table
    表空间那样释放回操作系统。

  • ALTER TABLE … DISCARD TABLESPACE
     和 ALTER TABLE …IMPORT TABLESPACE
    对于属于常规表空间的表不支持。

  • MySQL5.7.24不赞成在常规表空间中放置表分区,MySQL8.0.13中删除了这种支持。

  • 在源和副本驻留在同一主机上的复制环境中,不支持 ADD DATAFILE
    子句,因为它会导致源和副本在同一位置创建同名的表空间,这是不受支持的。但是,如果省略 ADD DATAFILE 子句,则在数据目录中创建表空间,生成的文件名是唯一的,这是允许的。

  • 从MySQL 8.0.21开始,除非 innodb 直接知道,否则不能在 undo 表空间目录(innodb_undo_directory
    )中创建常规表空间。已知目录是由 datadir
    innodb_data_home_dir
    innodb_directories
    变量定义的目录。


文章转载自我与风来,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论