#### 15.6.3.3 通用表空间

通用表空间是共享的`InnoDB`使用创建的表空间[`创建表空间`](create-tablespace.html)句法。本节中的以下主题描述了一般表空间功能和特性：

-   [通用表空间功能](general-tablespaces.html#general-tablespaces-capabilities)

-   [创建通用表空间](general-tablespaces.html#general-tablespaces-creating)

-   [将表添加到通用表空间](general-tablespaces.html#general-tablespaces-adding-tables)

-   [通用表空间行格式支持](general-tablespaces.html#general-tablespaces-row-format-support)

-   [使用 ALTER TABLE 在表空间之间移动表](general-tablespaces.html#general-tablespaces-moving-non-partitioned-tables)

-   [重命名通用表空间](general-tablespaces.html#general-tablespaces-renaming)

-   [删除通用表空间](general-tablespaces.html#general-tablespaces-dropping)

-   [一般表空间限制](general-tablespaces.html#general-tablespaces-limitations)

##### 通用表空间功能

通用表空间提供以下功能：

-   与系统表空间类似，通用表空间是能够为多个表存储数据的共享表空间。

-   通用表空间具有潜在的内存优势[每表文件表空间](innodb-file-per-table-tablespaces.html).服务器在表空间的整个生命周期内将表空间元数据保存在内存中。与单独的 file-per-table 表空间中相同数量的表相比，较少的通用表空间中的多个表消耗的表空间元数据内存更少。

-   一般表空间数据文件可以放置在相对于或独立于 MySQL 数据目录的目录中，为您提供了很多数据文件和存储管理能力[每表文件表空间](innodb-file-per-table-tablespaces.html).与 file-per-table 表空间一样，将数据文件放在 MySQL 数据目录之外的能力允许您单独管理关键表的性能，为特定表设置 RAID 或 DRBD，或者将表绑定到特定磁盘。

-   通用表空间支持所有表行格式和相关功能。

-   这`表空间`选项可以与[`创建表`](create-table.html)在通用表空间、file-per-table 表空间或系统表空间中创建表。

-   这`表空间`选项可以与[`更改表`](alter-table.html)在通用表空间、file-per-table 表空间和系统表空间之间移动表。

##### 创建通用表空间

通用表空间是使用创建的[`创建表空间`](create-tablespace.html)句法。

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

可以在数据目录中或在其外部创建通用表空间。为避免与隐式创建的 file-per-table 表空间冲突，不支持在数据目录下的子目录中创建通用表空间。在数据目录之外创建通用表空间时，该目录必须存在并且必须知道`InnoDB`在创建表空间之前。使未知目录已知`InnoDB`, 将目录添加到[`innodb_directories`](innodb-parameters.html#sysvar_innodb_directories)参数值。[`innodb_directories`](innodb-parameters.html#sysvar_innodb_directories)是只读启动选项。配置它需要重新启动服务器。

例子：

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

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

要么

```
mysql> CREATE TABLESPACE `ts1` Engine=InnoDB;
```

这`添加数据文件`从 MySQL 8.0.14 开始，子句是可选的，在此之前是必需的。如果`添加数据文件`创建表空间时未指定子句，则隐式创建具有唯一文件名的表空间数据文件。唯一文件名是一个 128 位 UUID，格式为五组由破折号分隔的十六进制数字 (*`aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeeeee`*）。通用表空间数据文件包括`.ibd`文件扩展名。在复制环境中，在源上创建的数据文件名与在副本上创建的数据文件名不同。

在数据目录之外的目录中创建通用表空间：

```
mysql> CREATE TABLESPACE `ts1` ADD DATAFILE '/my/tablespace/directory/ts1.ibd' Engine=InnoDB;
```

只要表空间目录不在数据目录下，您就可以指定相对于数据目录的路径。在这个例子中，`我的表空间`目录与数据目录处于同一级别：

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

笔记

这`引擎 = InnoDB`子句必须定义为[`创建表空间`](create-tablespace.html)声明，或`InnoDB`必须定义为默认存储引擎（[`default_storage_engine=InnoDB`](server-system-variables.html#sysvar_default_storage_engine)）。

##### 将表添加到通用表空间

创建通用表空间后，[`创建表 *`tbl_name`* ... 表空间 [=] *`表空间名称`*`](create-table.html)要么[`更改表 *`tbl_name`* 表空间 [=] *`表空间名称`*`](alter-table.html)语句可用于将表添加到表空间，如以下示例所示：

[`创建表`](create-table.html)：

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

[`更改表`](alter-table.html)：

```
mysql> ALTER TABLE t2 TABLESPACE ts1;
```

笔记

在 MySQL 5.7.24 中不推荐将表分区添加到共享表空间，并在 MySQL 8.0.13 中删除。共享表空间包括`InnoDB`系统表空间和通用表空间。

有关详细的语法信息，请参阅[`创建表`](create-table.html)和[`更改表`](alter-table.html).

##### 通用表空间行格式支持

通用表空间支持所有表行格式（`多余的`,`袖珍的`,`动态的`,`压缩`) 需要注意的是，由于物理页面大小不同，压缩表和未压缩表不能在同一个通用表空间中共存。

对于包含压缩表的通用表空间 (`ROW_FORMAT=压缩`）， 这`FILE_BLOCK_SIZE`必须指定选项，并且`FILE_BLOCK_SIZE`值必须是相对于[`innodb_页面大小`](innodb-parameters.html#sysvar_innodb_page_size)价值此外，压缩表的物理页面大小(`键块大小`)必须等于`文件块大小/1024`.例如，如果[`innodb_页面大小=16KB`](innodb-parameters.html#sysvar_innodb_page_size)和`文件块大小=8K`这个`键块大小`桌子的长度必须是8。

下表显示了允许的[`innodb_页面大小`](innodb-parameters.html#sysvar_innodb_page_size),`文件块大小`和`键块大小`组合。`文件块大小`值也可以以字节为单位指定。确定有效的`键块大小`给定值的值`文件块大小`，将`文件块大小`值乘以1024。32K和64K不支持表压缩`InnoDB`页面大小。有关`键块大小`看见[`创建表格`](create-table.html)和[第15.9.1.2节，“创建压缩表”](innodb-compression-usage.html).

[](<>)

**表15.3允许的页面大小、文件\_块\_尺寸和钥匙\_块\_压缩表的大小组合**

| InnoDB页面大小（InnoDB）\_页\_尺寸） | 允许的文件\_块\_大小值 | 许可密钥\_块\_大小值 |
| -------------------------- | ------------- | ------------ |
| 64KB | 64K（65536） | 不支持压缩 |
| 32KB | 32K（32768） | 不支持压缩 |
| 16KB | 16K（16384） | 没有一个如果[`innodb_页面大小`](innodb-parameters.html#sysvar_innodb_page_size)等于`文件块大小`，表空间不能包含压缩表。 |
| 16KB | 8K（8192） | 8. |
| 16KB | 4K（4096） | 4. |
| 16KB | 2K（2048） | 2. |
| 16KB | 1K（1024） | 1. |
| 8KB | 8K（8192） | 没有一个如果[`innodb_页面大小`](innodb-parameters.html#sysvar_innodb_page_size)等于`文件块大小`，表空间不能包含压缩表。 |
| 8KB | 4K（4096） | 4. |
| 8KB | 2K（2048） | 2. |
| 8KB | 1K（1024） | 1. |
| 4KB | 4K（4096） | 没有一个如果[`innodb_页面大小`](innodb-parameters.html#sysvar_innodb_page_size)等于`文件块大小`，表空间不能包含压缩表。 |
| 4KB | 2K（2048） | 2. |
| 4KB | 1K（1024） | 1. |

本例演示如何创建一个通用表空间并添加一个压缩表。该示例假设一个默认值[`innodb_页面大小`](innodb-parameters.html#sysvar_innodb_page_size)16KB。这个`文件块大小`8192要求压缩表具有`键块大小`共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;
```

如果您没有指定`文件块大小`创建常规表空间时，`文件块大小`默认为[`innodb_页面大小`](innodb-parameters.html#sysvar_innodb_page_size)什么时候`文件块大小`等于[`innodb_页面大小`](innodb-parameters.html#sysvar_innodb_page_size)，表空间只能包含未压缩行格式的表(`契约`, `冗余的`和`动态`行格式）。

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

[`改变桌子`](alter-table.html)和`表空间`选项可用于将表移动到现有的常规表空间、每个表空间的新文件或系统表空间。

笔记

MySQL 5.7.24不支持在共享表空间中放置表分区，并删除了MySQL 8.0.13。共享表空间包括`InnoDB`系统表空间和通用表空间。

要将表从文件表空间或系统表空间移动到常规表空间，请指定常规表空间的名称。通用表空间必须存在。看见[`改变表空间`](alter-tablespace.html)了解更多信息。

```
ALTER TABLE tbl_name TABLESPACE [=] tablespace_name;
```

要将表从常规表空间或每个表空间的文件移动到系统表空间，请指定`innodb_系统`作为表空间名称。

```
ALTER TABLE tbl_name TABLESPACE [=] innodb_system;
```

要将表从系统表空间或常规表空间移动到每个表空间的文件，请指定`innodb_文件_每个_表`作为表空间名称。

```
ALTER TABLE tbl_name TABLESPACE [=] innodb_file_per_table;
```

`改变桌子。。。表空间`操作会导致完整的表重建，即使`表空间`属性未更改其以前的值。

`改变桌子。。。表空间`语法不支持将表从临时表空间移动到持久表空间。

这个`数据目录`第条是允许的`创建表格。。。TABLESPACE=innodb_file_per_table`但在其他方面不支持与`表空间`选项从MySQL 8.0.21开始，在`数据目录`条款必须为所有人所知`InnoDB`。有关更多信息，请参阅[使用数据目录子句](innodb-create-table-external.html#innodb-create-table-external-data-directory).

从加密的表空间移动表时会受到限制。看见[加密限制](innodb-data-encryption.html#innodb-data-encryption-limitations).

##### 重命名常规表空间

支持使用重命名常规表空间[`改变表空间。。。改名为`](alter-tablespace.html)语法。

```
ALTER TABLESPACE s1 RENAME TO s2;
```

这个[`创建表空间`](privileges-provided.html#priv_create-tablespace)重命名常规表空间需要特权。

`改名为`操作是在中隐式执行的[`自动提交`](server-system-variables.html#sysvar_autocommit)模式而不考虑[`自动提交`](server-system-variables.html#sysvar_autocommit)背景

A.`改名为`操作无法在运行时执行[`锁桌`](lock-tables.html)或[`用读锁冲洗桌子`](flush.html)对驻留在表空间中的表有效。

独家[元数据锁](glossary.html#glos_metadata_lock)在重命名表空间时，在常规表空间内的表上执行，这会防止并发DDL。支持并发DML。

##### 删除常规表空间

这个[`删除表空间`](drop-tablespace.html)语句用于删除`InnoDB`通用表空间。

所有表都必须在删除之前从表空间中删除[`删除表空间`](drop-tablespace.html)活动如果表空间不是空的，[`删除表空间`](drop-tablespace.html)返回一个错误。

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

```
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    |
+------------+------------+
```

将军`InnoDB`删除表空间中的最后一个表时，不会自动删除表空间。必须使用[`删除表空间*`表空间名称`*`](drop-tablespace.html).

通用表空间不属于任何特定的数据库。A.[`删除数据库`](drop-database.html)操作可以删除属于常规表空间的表，但不能删除该表空间，即使[`删除数据库`](drop-database.html)操作将删除属于该表空间的所有表。

与系统表空间类似，截断或删除存储在通用表空间中的表会在通用表空间内部创建空闲空间[.ibd数据文件](glossary.html#glos_ibd_file)只能用于新的`InnoDB`数据空间不会像每个表的一个文件表空间在运行期间被删除时那样释放回操作系统[`升降台`](drop-table.html)活动

这个例子演示了如何删除`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中区分大小写的标识符。

##### 一般表空间限制

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

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

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

-   与系统表空间类似，截断或删除存储在通用表空间中的表会在通用表空间内部创建空闲空间[.ibd数据文件](glossary.html#glos_ibd_file)只能用于新的`InnoDB`数据空间不会像以前那样释放回操作系统[每个表的文件数](glossary.html#glos_file_per_table)表空间。

    此外，还有一个表复制[`改变桌子`](alter-table.html)对驻留在共享表空间（通用表空间或系统表空间）中的表的操作可能会增加表空间使用的空间量。这样的操作需要的额外空间与表中的数据加索引一样多。表复制所需的额外空间[`改变桌子`](alter-table.html)操作不会像针对每个表的文件表空间那样释放回操作系统。

-   [`改变桌子。。。丢弃表空间`](alter-table.html)和[`改变桌子。。。导入表空间`](alter-table.html)属于常规表空间的表不支持。

-   MySQL 5.7.24不支持在常规表空间中放置表分区，而MySQL 8.0.13则取消了这种支持。

-   这个`添加数据文件`子句在源和副本位于同一主机上的复制环境中不受支持，因为它会导致源和副本在同一位置创建同名的表空间，这是不受支持的。然而，如果`添加数据文件`子句，则表空间是在数据目录中创建的，其生成的文件名是唯一的，这是允许的。

-   从MySQL 8.0.21开始，无法在undo tablespace目录中创建常规表空间([`innodb_undo_目录`](innodb-parameters.html#sysvar_innodb_undo_directory))除非大家都知道`InnoDB`.已知目录是由[`数据目录`](server-system-variables.html#sysvar_datadir), [`innodb_数据_主页_目录`](innodb-parameters.html#sysvar_innodb_data_home_dir)和[`innodb_目录`](innodb-parameters.html#sysvar_innodb_directories)变量。
