什么是表空间,为什么要使用它?

What is a tablespace and why is it used?

在调查问题时,我遇到了这个错误:

30503 [ERROR] InnoDB: Attempted to open a previously opened tablespace. Previous tablespace mysql/innodb_index_stats uses space ID: 2 at filepath: ./mysql/innodb_index_stats.ibd. Cannot open tablespace Mydb/be_command_log which uses space ID: 2 at filepath: ./Mydb/be_command_log.ibd

在阅读了有关此问题的一些内容后,我才知道这是 a known issue of MySQL

但我的问题是我不太了解表空间的实际工作原理。它们有什么用?我读了 this definition,但它没有提供所有信息。

有人可以分享一些关于什么是表空间及其工作原理的详细信息吗?

默认情况下,InnoDB只包含一个tablespace调用系统tablespace,其标识符为0。更多tablespaces 可以使用 innodb_file_per_table 配置参数间接创建。 tablespace 由文件链组成。文件的大小不必被数据库块大小整除,因为我们可能只保留最后一个不完整的块未使用。当新文件附加到 tablespace 时,还会指定文件的最大大小。目前,我们认为最好在创建文件时就将文件扩展到最大大小,因为这样我们就可以避免在 table 需要更多 space 时动态扩展文件]space。数据文件是动态扩展的,但重做日志文件是预先分配的。另外,如前所述,只有系统 tablespace 可以拥有多个数据文件。还明确提到,即使 tablespace 可以有多个文件,它们也被认为是一个连接在一起的大文件。所以 tablespace 中的文件顺序很重要。

来自https://blogs.oracle.com/mysqlinnodb/entry/data_organization_in_innodb

MySQL Innodb TableSpace 是数据驻留在磁盘中的位置,称为 数据目录 (默认情况下 “系统 table 空间” )。示例:

"/var/lib/mysql"

从 MySQL 版本 5.6.6 开始,用户可以创建和指定他们想要存储数据的 table 空间,从而实现数据操作和恢复过程的吞吐量。 InnoDB 的 file-per-table 功能提供每个 tables 有单独的 .ibd 数据和索引文件,代表一个单独的通用 table 空间。这样一个数据库中的每个table都可以指向various locations of data directories.

例如:

/home/{user}/test/data/{dbName}/{tableName}.ibd

/home/{user}/work/data/{dbName}/{tableName}.ibd

有关每个 table table 空间的文件的更多信息,请参阅此 mysql documentation

sql 客户端应仅使用 sql 对象,而不关心数据库服务器物理存储该信息的位置。

这就是为什么需要 table空间的概念。 sql 像 table 数据这样的对象从 sql 客户端的角度进入 table 空间。

数据库服务器管理员现在可以自由地将 table 空间实际放置在他们想要的物理位置,sql 客户端程序仍然有效。

一个数据文件,可以保存一个或多个 InnoDB table 和相关索引的数据。

有多种类型的table根据配置w.r.t信息俱乐部每个table空间。这些是,

一个。系统table空间 b.每个 table 空间的文件 C。一般table空间

系统table空间包含,

  1. InnoDB 数据字典。
  2. 双写缓冲区。
  3. 更改缓冲区
  4. 撤消日志。

除此之外还包含,

  1. 表格和
  2. 索引数据

关联文件是 .idbdata1

innodb_file_per_table 选项 在 MySQL 5.6 及更高版本中默认启用,允许在文件中创建 tables -per-table table 空间,每个 table 有一个单独的数据文件。启用 innodb_file_per_table 选项可以使用其他 MySQL 功能,例如 table 压缩和传输 table table 空间。

关联文件是 .idbd

InnoDB 在 MySQL 5.7.6 中引入了通用的 tablespaces。一般 table 空间是使用 CREATE TABLESPACE 语法创建的共享 table 空间。它们可以在 MySQL 数据目录之外创建,能够容纳多个 table,并支持所有行格式的 table。

添加@BhupeshPant 提供的出色答案

InnoDB 的存储分为table空间。 Table空间是与多个数据文件(对象)关联的逻辑结构。每个 table 空间包含页面(块)、范围和段。

Pages - InnoDB 的最小数据块,也称为块。一页可以容纳一行或多行,具体取决于行大小。

一般来说,每个 table 都有自己的 table 与一个数据文件关联的空间

以下命令显示table空间和相应数据文件的完整列表-

SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES;

为了获得更正确的理解,请创建示例数据库 - database1

CREATE DATABASE database1;
USE database1;

现在创建一个示例table table1 -

CREATE TABLE table1 (
    -> col1 INT
    -> );

现在可以看到对应的table空间和数据文件也已经创建好了-

SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES;

+--------------------------+--------------------------+
| TABLESPACE_NAME          | FILE_NAME                |
+--------------------------+--------------------------+
|database1/table1          | ./database1/table1.ibd   |
+--------------------------+--------------------------+

这里的 .ibd 扩展名表示 Innodb 数据文件

现在创建另一个示例 table table2 -

CREATE TABLE table2 (
    -> col1 INT
    -> );

我们又可以看到对应的table空间和数据文件已经创建好了-

SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES;

+---------------------------+--------------------------+
| TABLESPACE_NAME           | FILE_NAME                |
+---------------------------+--------------------------+
| database1/table1          | ./database1/table1.ibd   |
| database1/table2          | ./database1/table2.ibd   |
+---------------------------+--------------------------+

此处系统正在为table空间创建默认名称。这些系统生成的 table 空间称为 - Single-Table tablespaces

单-Table table只有当innodb_file_per_tableON

时系统才会创建空间

可以通过-

查看
SHOW VARIABLES LIKE "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+

默认情况下,值为 ON。它可以通过 -

关闭
SET GLOBAL innodb_file_per_table = OFF;

SHOW VARIABLES LIKE "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | OFF   |
+-----------------------+-------+

如果该值关闭,则不会创建单Table table空间。

为了证明这一点,我们再次创建一个示例 table -

CREATE TABLE table10 (
    -> col1 INT
    -> );

SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES;

+---------------------------+--------------------------+
| TABLESPACE_NAME           | FILE_NAME                |
+---------------------------+--------------------------+
| database1/table1          | ./database1/table1.ibd   |
| database1/table2          | ./database1/table2.ibd   |
+---------------------------+--------------------------+

因此,我们可以看到没有创建名为 - database1/table10 的 table空间

在这种情况下,table 存储在 innodb_system table 空间;

SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES WHERE FILE_NAME LIKE "%ibdata1";
+-----------------+-----------+
| TABLESPACE_NAME | FILE_NAME |
+-----------------+-----------+
| innodb_system   | ./ibdata1 |
+-----------------+-----------+

但这不是一个好的做法,因为它会给系统 table空间带来更多负担,从而导致与性能相关的问题。

在系统生成 table 空间的情况下,删除 table 时 table 空间也会自动删除。




还有另一种类型的 tablespace 称为 - General Tablespaces,我们可以在其中为 tablespace 创建自定义名称。

为此,我们需要发出以下命令 -

CREATE TABLESPACE tablespace1 ADD DATAFILE '/var/lib/mysql/tablespace1.ibd' engine = Innodb;

我们可以检查table空间和相应的数据文件是否已经创建 -

SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES;

+---------------------------+--------------------------------+
| TABLESPACE_NAME           | FILE_NAME                      |
+---------------------------+--------------------------------+
| database1/table1          | ./database1/table1.ibd         |
| database1/table2          | ./database1/table2.ibd         |
| tablespace1               | /var/lib/mysql/tablespace1.ibd |
+---------------------------+--------------------------------+

这里所有的table空间都是在Mysqldatadir中创建的,默认情况下是/var/lib/mysql/

datadir值可以通过以下命令查看-

SELECT @@datadir;
+-----------------+
| @@datadir       |
+-----------------+
| /var/lib/mysql/ |
+-----------------+

在 MySQL 中,每个 table 空间只能添加一个数据文件。但在 Oracle 或 SQL 服务器中,可以将多个数据文件添加到一个 table 空间。

要在 table 空间中创建一个 table - tablespace1 我们需要发出命令 -

CREATE TABLE table3 (
    -> col1 INT 
    -> )
    -> TABLESPACE = tablespace1;

如果是一般的table空间,一个table空间内可以创建多个table -

CREATE TABLE table4 (
    -> col1 INT
    -> )
    -> TABLESPACE = tablespace1;

创建 table空间时,数据文件的位置可能不会单独说明。以下命令也将起作用 -

CREATE TABLESPACE tablespace2 ADD DATAFILE 'tablespace2.ibd' engine = Innodb;

SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES;

+---------------------------+--------------------------------+
| TABLESPACE_NAME           | FILE_NAME                      |
+---------------------------+--------------------------------+
| database1/table1          | ./database1/table1.ibd         |
| database1/table2          | ./database1/table2.ibd         |
| tablespace1               | /var/lib/mysql/tablespace1.ibd |
| tablespace2               | ./tablespace2.ibd              |
+---------------------------+--------------------------------+

默认情况下,所有 table 空间都在 datadir 目录中创建

Tablespace 创建默认值的页面大小。但是,我们也可以在创建 table 空间时设置自己的页面大小。但是,大小必须在默认页面大小以内,否则会出错。默认页面大小可以在 MySQL 服务器安装期间设置。

允许的页面大小为 - 4 kb、8 kb、16 kb、32 kb、64 kb。

通常在安装过程中,默认页面大小设置为 16 kb。

以下命令用于查看默认页面大小-

SHOW VARIABLES LIKE 'innodb_page_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+

创建具有自定义页面大小的 table空间的命令是 -

CREATE TABLESPACE tablespace3_8kb ADD DATAFILE '/var/lib//mysql/tablespace3_8kb.ibd' FILE_BLOCK_SIZE = 8192 ENGINE = Innodb;

SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES;

+---------------------------+-------------------------------------+
| TABLESPACE_NAME           | FILE_NAME                           |
+---------------------------+-------------------------------------+
| database1/table1          | ./database1/table1.ibd              |
| database1/table2          | ./database1/table2.ibd              |
| tablespace1               | /var/lib/mysql/tablespace1.ibd      |
| tablespace2               | ./tablespace2.ibd                   |
| tablespace3_8kb           | /var/lib//mysql/tablespace3_8kb.ibd |
+---------------------------+-------------------------------------+

要将 table 存储在具有用户定义页面大小的 table 空间中,需要不同的语法 -

CREATE TABLE table5 (
    -> col1 INT
    -> )
    -> TABLESPACE = tablespace3_8kb 
    -> KEY_BLOCK_SIZE = 8;

与系统生成的 table 空间不同,如果我们删除 table 空间,一般 table 空间不会自动删除,需要明确删除 table 空间.

命令是-

DROP TABLESPACE tablespace_name;