15.6.3.3—通用表空间

通用表空间是指通过create tablespace语法创建的共享的InnoDB表空间。本章从以下几个方面描述通用表空间的功能和特性:

通用表空间的功能 #

通用表空间提供如下功能:

  • 和系统表空间相似,通用表空间是供不同的表存储数据用的共享表空间。
  • 和独立表空间相比,通用表空间有潜在的内存优势。服务器会在内存中保留表空间的元数据。对于相同数量的多张表来说,使用通用表空间比使用独立表空间使用更少的内存来存储表空间元数据。
  • 通用表空间的数据文件可以存放在MySQL数据目录下, 也可以存放在独立目录下。这提供了许多独立表空间具有的数据文件和存储管理功能。对于独立表空间来说,可以在MySQL数据目录之外存储数据文件的功能允许你可以独立管理部分关键表的性能(比如,让部分表使用RAID或DRBD,或将部分表和特定磁盘绑定)。
  • 通用表空间支持所有的表记录格式和相关特性。
  • 可以在CREATE TABLE时添加TABLESPACE选项来在选择是在通用表空间还是在独立表空间,或是系统表空间中创建表。
  • 可以在ALTER TABLE时使用TABLESPACE选项赖在不同表空间之间移动表。

创建一个通用表空间 #

使用CREATE TABLESPACE语法来创建通用表空间:

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

通用表空间可以存储在数据目录下,也可以不在里面。为了避免和创建独立表空间文件冲突,不支持在数据目录的子目录下创建通用表空间。当不在数据目录下创建系统表空间时,这个目录必须已经存在并且对于InnoDB可见。要想让一个InnoDB不可知的目录对于InnoDB可知,可以在innodb_directories参数值中添加这个目录。innodb_directories是一个只读的启动选项。修改这个设置需要重启服务。

例如: 在数据目录下创建一个通用表空间:

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

mysql> CREATE TABLESPACE `ts1` Engine=InnoDB;

在MySQL8.0.14之前ADD DATAFILE子句是必须的,从MySQL8.0.14开始,是可选的。如果在创建表空间时没有ADD DATAFILE子句,就会为其创建一个文件名独一无二的表空间文件。这个文件名是一个128位的UUID格式的。通用表空间文件名包含一个.ibd文件扩展。在一个复制环境中,副本上的数据文件名和源库上的不一样。

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

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;
CREATE TABLESPACE语句必须带上ENGINE = InnoDB子句,否则必须指定InnoDB位默认存储引擎(default_storage_engine=InnoDB)。

向通用表空间中添加表 #

创建通用表空间之后,可以使用CREATE TABLE tbl_name … tablespace [=] tablespace_name或alter table tbl_name tablespace [=] tablespace_name语句来向表空间中添加表,如下所示: CREATE TABLE:

mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1;

ALTER TABLE:

mysql> ALTER TABLE t2 TABLESPACE ts1;

向共享表空间中添加表分区的功能,从MySQL5.7.24开始弃用,在MySQL8.0.13中被移除。共享表空间包括InnoDB系统表空间和通用表空间。
向了解更多语法信息,请查看CREATE TABLEALTER TABLE

通用表空间记录格式支持 #

通用表控制支持所有的表记录格式(REDUNDANT,COMPACT,DYNAMIC,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_page_size,FILE_BLOCK_SIZE,和KEY_BLOCK_SIZE混合,也可以按字节指定FILE_BLOCK_SIZE的值。对于一个给定的FILE_BLOCK_SIZE,要确定一个可行的KEY_BLOCK_SIZE,将FILE_BLOCK_SIZE的值除以1024。对于32K和64K的InnoDB页,不支持表压缩。想了解更多关于KEY_BLOCK_SIZE的信息,请查看CREATE TABLE,和章节 15.9.1.2,“创建压缩表”

表15.3 压缩表允许的页大小,FILE_BLOCK_SIZE,和KEY_BLOCK_SIZE混合

innodb_page_sizeFILE_BLOCK_SIZEKEY_BLOCK_SIZE
64KB64KB不支持压缩
32KB32KB不支持压缩
16KB16KB
16KB8KB8
16KB4KB4
16KB2KB2
16KB1KB1
8KB8KB
8KB4KB4
8KB2KB2
8KB1KB1
4KB4KB
4KB2KB2
4KB1KB1

下面的例子展示了怎样创建一个通用表空间并添加一个压缩表。这个例子使用默认的innodb_page_size=16KB。FILE_BLOCK_SIZE=8KB,KEY_BLOCK_SIZE=8。

mysql> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
mysql> CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;

如果你在创建一个通用表空间时不指定FILE_BLOCK_SIZE,FILE_BLOCK_SIZE会默认设置成innodb_page_size。当FILE_BLOCK_SIZE和innodb_page_size相等时,表空间只能包含非压缩行格式的表(COMPACT,REDUNDANT和DYNAMIC).

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

可以使用带TABLESPACE选项的ALTER TABLE来将一张表从一个已存在的通用表空间移动到一个新的独立表空间,或者移动到系统表空间。

在共享表空间中支持分区表的功能,在MySQL5.7.24中被启用,从MySQL8.0.13中移除。共享表空间包括InnoDB系统表空间和通用表空间。

要将一张表从一个独立表空间或系统表空间移动到一个通用表空间,指定通用表空间的名称。通用表空间必须已存在。想查看更多信息,请查阅ALTER TABLESPACE。

ALTER TABLE tbl_name TABLESPACE [=] tablespace_name;

要将一张表从一个通用表空间或独立表空间移动到一个系统表空间,表空间名称指定为innodb_system。

ALTER TABLE tbl_name TABLESPACE [=] innodb_system;

要将一张表从一个系统表空间或一个通用表空间移动到一个独立表空间,将表空间名指定为innodb_file_per_table。

ALTER TABLE tbl_name TABLESPACE [=] innodb_file_per_table;

ALTER TABLE … TABLESPACE操作会导致一次全表重建,即使TABLESPACE属性没有改变。

ALTER TABLE … TABLESPACE语法不支持将一张表从一个临时表空间移动到一个永久表空间。

CREATE TABLE … TABLESPACE=innodb_file_per_table语法允许DATA DIRECTORY子句,但是并不支持和TABLESPACE选项一起使用。从MySQL8.0.21开始,DATA DIRECTORY子句指定的目录必须对于InnoDB可知。想要了解更多信息,请查看使用DATA DIRECTORY子句

在从加密表空间移动表时,限制同样适用,见加密限制

重命名通用表空间 #

可以使用ALTER TABLESPACE … RENAME TO 语法来重命名一个通用表空间:

ALTER TABLESPACE s1 RENAME TO s2;

重命名表空间需要CREATE TABLESPACE权限。

不管autocommit设置如何,RENAME TO 操作都会使用autocommit模式。

在LOCK TABLES或FLUSH TABLES WITH READ LOCK语句生效时,不能执行RENAME TO操作。

在重命名表空间时,会对其中的表添加排它性元数据锁,这会阻止并发DDL。允许并发DML操作。

删除通用表空间 #

可以使用DROP TABLESPACE语法来删除一个InnoDB通用表空间。

在执行DROP TABLESPACE操作之前,必须删除其中的所有表。如果表空间不是空的,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 |
+------------+------------+

当通用表空间中的最后一张表被删除时,表空间并不会自动删除。必须显式执行DROP TABLESPACE tablespace_name来删除表空间。

一个通用表空间并不从属于任何特定数据库。一个DROP DATABASE操作可以删除通用表空间中的表,但是不能删除这个表空间,即使这个DROP DATABASE操作删除了这个表空间中所有的表。

和系统表空间相似,清空或删除存储在通用表空间中的表会在通用表空间内部产生空闲空间。.idb数据文件只能被用于新的InnoDB数据。和独立表空间表使用DROB TABLE操作时会删除表空间文件不同,(对于通用表空间来说)空间也不会被归还给操作系统。

下面的例子展示了怎样删除一个InnoDB通用表空间。通用表空间ts1中只有一张表。在伤处这个表空间之前,必须删除这张表。

mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1 Engine=InnoDB;
mysql> DROP TABLE t1;
mysql> DROP TABLESPACE ts1;
在MySQL中tablespace_name是大小写敏感的。

通用表空间的限制 #

  • 一个生成的或已存在的表空间不能被转换为一个通用表空间。

  • 不支持创建临时通用表空间。

  • 通用表空间不支持临时表。

  • 和系统表空间相似,清空或删除通用表空间中的表会在通用表空间.ibd数据文件内部产生空闲空间,这可以被用于新的InnoDB数据。和独立表空间不同,空间不会被释放给操作系统。

    此外,对一个共享表空间中的表进行复制表类型的ALTER TABLE操作,会使表空间占用的空间增加。此类 操作所需的额外空间与表中的数据加索引所需的空间一样多。和独立表空间不同,对于通用表空间类说,表复制类型的ALTER TABLE操作所使用的多余空间不会被释放返回给操作系统。

    • 对于从属于一个通用表空间中的表,不支持ALTER TABLE … DISCARD TABLESPACE和ALTER TABLE … IMPORT TABLESPACE操作。

    • 通用表空间对分区表的支持在5.7.24中被废弃,在8.0.13中被移除。

    • 如果源库和副本在同一台主机上,那么在副本中不支持ADD DATAFILE子句,因为这可能会导致源本和副本在同一个位置创建表空间文件。但是,如果不带ADD DATAFILE子句,会在数据目录中生成一个唯一的表空间文件名,这是允许的。

    • 从MySQL8.0.21开始,不能在undo表空间目录(innodb_undo_directory)下创建通用表空间,除非这对InnoDB来说,是明确可知的。可知的目录是指通过以下变量定义的:datadir,innodb_data_home_dir,以及innodb_directories。