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

48

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

30503 [ERROR] InnoDB: 试图打开一个先前已打开的表空间。 先前的表空间 mysql/innodb_index_stats 使用文件路径为./mysql/innodb_index_stats.ibd的空间ID:2。无法打开使用空间ID:2和文件路径为./Mydb/be_command_log.ibd的表空间 Mydb/be_command_log

阅读一些关于此问题的资料后,我得知这是MySQL的已知问题

但我的问题是我不太了解表空间的工作原理。它们有什么用处?我阅读了这个定义,但它并没有提供所有信息。

有人可以分享一些详细的关于表空间是什么以及它们如何工作的信息吗?


这篇文章还为您提供了一些关于表空间的背景信息:http://stackoverflow.com/questions/18959643/what-is-the-use-of-tablespace-in-the-above-query - ArBro
我认为@ABr提供的链接回答了这个问题,但是由于你标记了MySQL,你可能也对CREATE TABLESPACE语句感兴趣。 - bishop
同意这一点,但取决于您的 MySql 版本,您可能希望查看 5.7 发行版的参考文档:http://dev.mysql.com/doc/refman/5.7/en/create-tablespace.html - ArBro
几乎没有任何运行MySQL的人需要了解"表空间"这个术语。请提供SHOW CREATE TABLE和其他相关信息以了解正在发生的情况。 - Rick James
你最近更新到了5.6.15吗?是从哪个版本更新的?你运行了 mysql_update 吗? - Rick James
显示剩余2条评论
5个回答

23

一个可容纳一个或多个InnoDB表及其关联索引数据的数据文件。

根据每个表的信息组合配置,有许多类型的表空间。这些是:

a. 系统表空间 b. 每个表的文件表空间 c. 通用表空间

系统表空间包含:

  1. InnoDB数据字典
  2. DoubleWrite缓冲区
  3. 更改缓冲区
  4. Undo日志

除此之外,它还包含:

  1. 表格和
  2. 索引数据

相关文件为.idbdata1

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

相关文件为.idbd

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


15

在@BhupeshPant提供的优秀答案基础上,此处补充:

InnoDB的存储被划分为表空间。一个表空间是与多个数据文件(对象)相关联的逻辑结构。每个表空间包含页面(块)、区和段。

enter image description here

页面 - InnoDB中可容纳一个或多个行(取决于行大小)的最小数据单元,也称为块。

通常,每个表都有自己的表空间,与一个数据文件相关联。

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

SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES;

为了更好地理解,请创建一个示例数据库 - database1
CREATE DATABASE database1;
USE database1;

现在创建一个示例表 table1 -
CREATE TABLE table1 (
    -> col1 INT
    -> );

现在我们可以看到相应的表空间和数据文件也已被创建 -
SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES;

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

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

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

CREATE TABLE table2 (
    -> 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   |
+---------------------------+--------------------------+

这里系统正在为表空间创建默认名称。这些由系统生成的表空间称为 - 单表表空间 (Single-Table tablespaces)

只有当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   |
+-----------------------+-------+

如果该值关闭,将不会创建单表表空间。

为了演示这一点,我们再次创建一个示例表 -

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的表空间被创建。
在这种情况下,表格被存储在innodb_system表空间中。
SELECT TABLESPACE_NAME, FILE_NAME FROM information_schema.FILES WHERE FILE_NAME LIKE "%ibdata1";
+-----------------+-----------+
| TABLESPACE_NAME | FILE_NAME |
+-----------------+-----------+
| innodb_system   | ./ibdata1 |
+-----------------+-----------+

然而,这并不是一个好的实践,因为它会给系统表空间增加更多负担,导致性能相关问题。

在系统生成的表空间中,当删除表时,表空间也会自动被删除。




还有另一种类型的表空间,称为常规表空间,我们可以为表空间创建自定义名称。

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

CREATE TABLESPACE tablespace1 ADD DATAFILE '/var/lib/mysql/tablespace1.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 |
+---------------------------+--------------------------------+

所有的表空间都创建在Mysql的datadir中,默认情况下为/var/lib/mysql/

可以通过以下命令检查datadir的值 -

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

MySQL只允许在表空间中添加一个数据文件。但是在Oracle或SQL Server中,可以向表空间添加多个数据文件。

要在名为 tablespace1 的表空间中创建表,我们需要发出以下命令 -

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

对于一般的表空间,可以在一个表空间内创建多个表-

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

在创建表空间时,不一定需要专门指定数据文件的位置。以下命令也可以使用 -
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              |
+---------------------------+--------------------------------+

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

表空间会创建一个默认值的页面大小。但是,在创建表空间时我们也可以设置自己的页面大小。但是,该大小必须在默认页面大小范围内,否则会出现错误。默认页面大小可以在安装 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 |
+------------------+-------+

创建自定义页面大小的表空间的命令为 -
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 |
+---------------------------+-------------------------------------+

要将表存储到用户定义页面大小的表空间中,需要使用不同的语法-

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

通常由系统生成的表空间与一般表空间不同,如果我们删除表时,一般表空间不会自动删除,需要显式地将表空间删除。

命令是 -

DROP TABLESPACE tablespace_name;

7

MySQL InnoDB表空间是数据存储在磁盘上的位置,称为数据目录(默认为"系统表空间")。例如:

"/var/lib/mysql"

从MySQL 5.6.6版本开始,用户可以创建并指定要存储数据的表空间,从而实现数据操作和恢复过程的吞吐量。InnoDB的文件每表特性提供了每个表具有单独的.ibd数据和索引文件,代表一个单独的通用表空间。所以数据库中的每个表都可以指向各种数据目录的位置

例如:

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

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

关于单独表格表空间的更多信息,请参考mysql documentation


5
默认情况下,InnoDB只包含一个名为系统表空间的表空间,其标识符为0。可以使用innodb_file_per_table配置参数间接创建更多表空间。表空间由一系列文件组成。文件大小不必被数据库块大小整除,因为我们可以仅留下最后一个不完整的块未使用。当向表空间附加新文件时,还指定了文件的最大大小。目前,我们认为最好在创建文件时将文件扩展到其最大大小,因为这样可以避免在需要更多表空间空间时动态扩展文件。数据文件是动态扩展的,但重做日志文件是预分配的。此外,正如以前已经提到的那样,只有系统表空间可以有多个数据文件。还明确提到,即使表空间可以具有多个文件,但它们被视为连接在一起的单个大文件。因此,在表空间中文件的顺序很重要。
来源:https://blogs.oracle.com/mysqlinnodb/entry/data_organization_in_innodb

Rukshan,你能详细解释一下它们是什么以及为什么我们需要它们吗?感谢你的评论。 - Bhupesh Pant

2

SQL客户端只能使用SQL对象,不需要关心数据库服务器物理存储信息的位置。

这就是为什么需要表空间的概念。从SQL客户端的角度来看,SQL对象(如表数据)进入表空间。

现在,数据库服务器管理员可以自由地将表空间物理放置在他们想要的位置,而SQL客户端程序仍然可以正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接