文章目录
- MySQL 8.0 InnoDB Tablespaces之General Tablespaces(通用表空间/一般表空间)
- General tablespaces(通用表空间/一般表空间)
- 通用表空间的功能
- 通用表空间的限制
- 创建通用表空间(一般表空间)
- 创建语法
- 创建通用表空间
- 例1:不指定数据文件路径
- 例2: 省略add datafile语句
- 例3:创建datadir路径外的表空间
- innodb_directories变量参数
- 例:创建datadir路径外的表空间
- 修改innodb_directories变量参数
- 创建datadir路径外的表空间
- 例4:创建InnoDB通用表空间的限制
- 通用表空间中的表
- 例1:创建表指定通用表空间
- 例2:修改表的表空间
- 例2-1:修改到不同的通用表空间中
- 例2-2:修改表从独立表空间或系统表空间到通用表空间
- 例2-3:修改表从通用表空间或系统表空间到独立表空间
- 例2-4:修改表从通用表空间或独立表空间到系统表空间
- 参考
【免责声明】文章仅供学习交流,观点代表个人,与任何公司无关。
编辑|SQL和数据库技术(ID:SQLplusDB)
MySQL 8.0 OCP (1Z0-908) 考点概要
MySQL 8.0 OCP (1Z0-908) 考点精析-安装与配置考点1:设置系统变量
【MySQL】控制MySQL优化器行为方法之optimizer_switch系统变量
【MySQL】MySQL系统变量(system variables)列表(mysqld --verbose --help的结果例)
【MySQL】MySQL系统变量(system variables)列表(SHOW VARIABLES 的结果例)
MySQL 8.0 OCP (1Z0-908) 考点精析-备份与恢复考点1:MySQL Enterprise Backup概要
MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点1:sys.statement_analysis视图
MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点2:系统变量的确认
MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点3:EXPLAIN ANALYZE
MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点4:慢速查询日志(slow query log)
MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点5:表连接算法(join algorithm)
MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点6:MySQL Enterprise Monitor之Query Analyzer
MySQL 8.0 OCP (1Z0-908) 考点精析-架构考点1:二进制日志文件(Binary log)
MySQL 8.0 OCP (1Z0-908) 考点精析-架构考点5:数据字典(Data Dictionary)
MySQL 8.0 OCP (1Z0-908) 考点精析-架构考点6:InnoDB Tablespaces之系统表空间(System Tablespace)
MySQL 8.0 InnoDB Tablespaces之File-per-table tablespaces(单独表空间)
MySQL 8.0 InnoDB Tablespaces之General Tablespaces(通用表空间/一般表空间)
InnoDB表空间是MySQL中用于存储InnoDB存储引擎表数据和索引的物理文件。
InnoDB表空间根据用途可以分成多种类型:
- 数据表空间:
- System tablespace(系统表空间)
- File-per-table tablespaces(单独表空间)
- General tablespaces(通用表空间/一般表空间)
- Undo 表空间
- 临时表空间(Temporary table tablespaces)
General tablespaces(通用表空间/一般表空间)
通用表空间具有如下功能和限制。
通用表空间的功能
通用表空间具有如下功能:
- 使用CREATE TABLESPACE语法创建的共享InnoDB表空间(与Oracle的表空间很相似)。
- 类似于系统表空间,通用表空间是共享表空间,可以存储多个表的数据。 与独立表空间相比,通用表空间具有潜在的内存优势。(通用表空间中多个表共享一个表空间,所以消耗更少的内存用于表空间元数据,独立表空间需要更多内存用于表空间元数据。)
- 数据文件可以放置在与MySQL数据目录( MySQL data directory)相关或独立的目录中。
- 通用表空间支持所有的表行格式和相关功能(REDUNDANT, COMPACT, DYNAMIC, COMPRESSED)。 CREATE
- TABLE语句可以使用TABLESPACE选项在通用表空间、独立表空间或系统表空间中创建表。 ALTER
- TABLE语句可以使用TABLESPACE选项在通用表空间、独立表空间或系统表空间之间移动表。
- 创建通用表空间时候会生成相应的.ibd数据文件。 通用表空间不属于特定的数据库。
通用表空间的限制
通用表空间具有如下限制:
- 无法将现有的表空间更改为通用表空间。
- 不支持创建临时通用表空间。
- 通用表空间不支持临时表。
- 与系统表空间类似,truncate 或者drop通用表空间中的表,仅释放系统表空间中的空间,不会返回给操作系统。
- 表复制的ALTER TABLE操作可能会增加表空间使用的空间量。
- 不支持表分区(table partitions)放置在通用表空间中
- 源和副本位于同一主机上的复制环境中,不支持使用ADD DATAFILE子句。
- MySQL 8.0.21开始,由datadir、innodb_data_home_dir和innodb_directories变量定义的目录以外,无法在撤销表空间目录(innodb_undo_directory)中创建通用表空间。
创建通用表空间(一般表空间)
创建语法
通用表空间/一般表空间创建语法如下:
CREATE [UNDO] TABLESPACE tablespace_name
InnoDB and NDB:
[ADD DATAFILE 'file_name']
[AUTOEXTEND_SIZE [=] value]
InnoDB only:
[FILE_BLOCK_SIZE = value]
[ENCRYPTION [=] {'Y' | 'N'}]
NDB only:
USE LOGFILE GROUP logfile_group
[EXTENT_SIZE [=] extent_size]
[INITIAL_SIZE [=] initial_size]
[MAX_SIZE [=] max_size]
[NODEGROUP [=] nodegroup_id]
[WAIT]
[COMMENT [=] 'string']
InnoDB and NDB:
[ENGINE [=] engine_name]
Reserved for future use:
[ENGINE_ATTRIBUTE [=] 'string']
创建通用表空间
例1:不指定数据文件路径
可以不指定数据文件路径创建通用表空间,这时候数据文件会默认创建在datadir路径下。
创建表空间:
mysql> create tablespace test_tbs1 add datafile 'test_tbs1.ibd';
Query OK, 0 rows affected (0.01 sec)
mysql> show variables like 'datadir';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| datadir | /var/lib/mysql/ |
+---------------+-----------------+
1 row in set (0.01 sec)
mysql> select * from
-> information_schema.innodb_tablespaces t
-> join information_schema.innodb_datafiles d
-> on t.SPACE=d.SPACE
-> where t.NAME ='test_tbs1'\G
*************************** 1. row ***************************
SPACE: 81
NAME: test_tbs1
FLAG: 18432
ROW_FORMAT: Any
PAGE_SIZE: 16384
ZIP_PAGE_SIZE: 0
SPACE_TYPE: General
FS_BLOCK_SIZE: 4096
FILE_SIZE: 114688
ALLOCATED_SIZE: 114688
AUTOEXTEND_SIZE: 0
SERVER_VERSION: 8.0.35
SPACE_VERSION: 1
ENCRYPTION: N
STATE: normal
SPACE: 0x3831
PATH: test_tbs1.ibd
1 row in set (0.00 sec)
mysql>
查看数据文件:
root@mysql-vm:/var/lib/mysql# ls -l test_tbs*
-rw-r----- 1 mysql mysql 114688 Dec 20 20:32 test_tbs1.ibd
例2: 省略add datafile语句
MySQL 8.0.14版本之后,创建表空间时可以省略add datafile语句。这时MySQL会隐式创建具有唯一文件名的表空间数据文件。
- 文件名是一个128位的UUID,格式为五组用破折号分隔的十六进制数字(aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee)。
- 常规表空间数据文件包括一个.ibd文件扩展名。 在replication环境中,在源上创建的数据文件名与在复制副本上创建的文件名不同。
例:
mysql> create tablespace test_tbs2;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from
-> information_schema.innodb_tablespaces t
-> join information_schema.innodb_datafiles d
-> on t.SPACE=d.SPACE
-> where t.NAME ='test_tbs2'\G
*************************** 1. row ***************************
SPACE: 82
NAME: test_tbs2
FLAG: 18432
ROW_FORMAT: Any
PAGE_SIZE: 16384
ZIP_PAGE_SIZE: 0
SPACE_TYPE: General
FS_BLOCK_SIZE: 4096
FILE_SIZE: 114688
ALLOCATED_SIZE: 114688
AUTOEXTEND_SIZE: 0
SERVER_VERSION: 8.0.35
SPACE_VERSION: 1
ENCRYPTION: N
STATE: normal
SPACE: 0x3832
PATH: af5bb7e2-9f34-11ee-8d33-525400b409f6.ibd
1 row in set (0.00 sec)
mysql>
查看数据文件:
root@mysql-vm:/var/lib/mysql# ls -l af5bb7e2-9f34-11ee-8d33-525400b409f6.ibd
-rw-r----- 1 mysql mysql 114688 Dec 20 20:38 af5bb7e2-9f34-11ee-8d33-525400b409f6.ibd
root@mysql-vm:/var/lib/mysql#
例3:创建datadir路径外的表空间
通用表空间数据文件可以放置在数据目录之外的位置,但是路径必须是innodb_directories的值或者附加到innodb_directories值的变量(innodb_data_home_dir、innodb_undo_directory和datadir)之一。
innodb_directories变量参数
innodb_directories变量参数内容如下:
Command-Line Format | –innodb-directories=dir_name |
---|---|
System Variable | innodb_directories |
Scope | Global |
Dynamic | No |
SET_VAR Hint Applies | No |
Type | Directory name |
Default Value | NULL |
innodb_directories参数的默认值为NULL。但是innodb_data_home_dir、innodb_undo_directory和datadir定义的目录会会附加到innodb_directories参数值上。
例:
mysql> show variables like 'innodb_directories';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| innodb_directories | |
+--------------------+-------+
1 row in set (0.01 sec)
mysql> show variables like 'innodb_data_home_dir';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| innodb_data_home_dir | |
+----------------------+-------+
1 row in set (0.00 sec)
mysql> show variables like 'innodb_undo_directory';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_undo_directory | ./ |
+-----------------------+-------+
1 row in set (0.01 sec)
mysql> show variables like 'datadir';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| datadir | /var/lib/mysql/ |
+---------------+-----------------+
1 row in set (0.00 sec)
mysql>
/var/lib/mysql-files
drwx------ 12 mysql mysql 4096 Dec 24 22:10 mysql
参考:
https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_directories
修改innodb_directories变量参数需要修改MySQL配置文件,并重新启动MySQL服务。
例:创建datadir路径外的表空间
如果在未定义路径中创建通用表空间,由于不是已知目录,会发生如下ERROR 3121 (HY000)错误。
mysql> show variables like 'innodb_directories';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| innodb_directories | |
+--------------------+-------+
1 row in set (0.01 sec)
mysql> create tablespace sqlplusdb_tb1 add datafile '/var/lib/mysql-files/sqlplusdb_tb1.ibd';
ERROR 3121 (HY000): The DATAFILE location must be in a known directory.
mysql>
可以通过修改innodb_directories变量参数添加已知目录。
修改innodb_directories变量参数
添加如下内容(innodb_directories=/var/lib/mysql-files)到MySQL配置文件中。
例:innodb_directories=/var/lib/mysql-files
root@mysql-vm:/etc/mysql# vi /etc/mysql/mysql.conf.d/mysqld.cnf
root@mysql-vm:/etc/mysql# systemctl stop mysql
root@mysql-vm:/etc/mysql# systemctl start mysql
创建datadir路径外的表空间
查看变量并创建datadir路径外的表空间的表空间
mysql> show variables like 'innodb_directories';
+--------------------+----------------------+
| Variable_name | Value |
+--------------------+----------------------+
| innodb_directories | /var/lib/mysql-files |
+--------------------+----------------------+
1 row in set (0.00 sec)
mysql> create tablespace test_tb3 add datafile '/var/lib/mysql-files/test_tb3.ibd';
Query OK, 0 rows affected (0.02 sec)
mysql>
mysql> select * from
-> information_schema.innodb_tablespaces t
-> join information_schema.innodb_datafiles d
-> on t.SPACE=d.SPACE
-> where t.NAME ='test_tb3'\G
*************************** 1. row ***************************
SPACE: 92
NAME: test_tb3
FLAG: 18432
ROW_FORMAT: Any
PAGE_SIZE: 16384
ZIP_PAGE_SIZE: 0
SPACE_TYPE: General
FS_BLOCK_SIZE: 4096
FILE_SIZE: 114688
ALLOCATED_SIZE: 114688
AUTOEXTEND_SIZE: 0
SERVER_VERSION: 8.0.35
SPACE_VERSION: 1
ENCRYPTION: N
STATE: normal
SPACE: 0x3932
PATH: /var/lib/mysql-files/test_tb3.ibd
1 row in set (0.00 sec)
mysql>
参考:
MySQL 8.0 OCP (1Z0-908) 考点精析-安装与配置考点1:设置系统变量
例4:创建InnoDB通用表空间的限制
可以在数据目录(datadir)中创建通用表空间。
mysql> create tablespace sqlplusdb_tb1 add datafile '/var/lib/mysql/sqlplusdb_tb1.ibd';
Query OK, 0 rows affected (0.02 sec)
但是为了避免与隐式创建的每个表一个文件的表空间发生冲突,不支持在数据目录(datadir)的子目录中创建InnoDB通用表空间。
如果在数据目录(datadir)的子目录中创建InnoDB通用表空间会报ERROR 3121 (HY000)错误。
例:
mysql> show variables like 'datadir';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| datadir | /var/lib/mysql/ |
+---------------+-----------------+
1 row in set (0.00 sec)
mysql> create tablespace sqlplusdb_tb2 add datafile '/var/lib/mysql/testdb/sqlplusdb_tb1.ibd';
ERROR 3121 (HY000): The DATAFILE location cannot be under the datadir.
mysql>
通用表空间中的表
和Oracle一样,MySQL在创建表时可以指定表空间也可以修改表的表空间。
例1:创建表指定通用表空间
mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> CREATE TABLE test_t1 (c1 INT) TABLESPACE test_tbs1 ;
Query OK, 0 rows affected (0.01 sec)
mysql>
mysql> SHOW CREATE TABLE test_t1;
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| test_t1 | CREATE TABLE `test_t1` (
`c1` int DEFAULT NULL
) /*!50100 TABLESPACE `test_tbs1` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)
mysql>
mysql> select
-> name as 'table_name',
-> space_type
-> from
-> information_schema.innodb_tables
-> where
-> name like '%test_t1%' \g
+----------------+------------+
| table_name | space_type |
+----------------+------------+
| testdb/test_t1 | General |
+----------------+------------+
1 row in set (0.08 sec)
例2:修改表的表空间
通过ALTER TABLE语句的TABLESPACE选项可以修改表的表空间,将表在通用表空间、独立表空间或系统表空间之间进行移动。
需要注意的是:
- ALTER TABLE ... TABLESPACE操作将导致对表进行全表重建(即使TABLESPACE属性未发生更改也会重建)。
- ALTER TABLE ... TABLESPACE语法不支持将表从临时表空间移动到持久表空间。
例2-1:修改到不同的通用表空间中
通过ALTER TABLE tbl_name TABLESPACE [=] tablespace_name修改表到不同的通用表空间中
例:
mysql> SHOW CREATE TABLE test_t1;
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| test_t1 | CREATE TABLE `test_t1` (
`c1` int DEFAULT NULL
) /*!50100 TABLESPACE `test_tbs1` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
mysql> ALTER TABLE test_t1 tablespace=sqlplusdb_tb1;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SHOW CREATE TABLE test_t1;
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test_t1 | CREATE TABLE `test_t1` (
`c1` int DEFAULT NULL
) /*!50100 TABLESPACE `sqlplusdb_tb1` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql>
例2-2:修改表从独立表空间或系统表空间到通用表空间
可以通过如下命令修改表从独立表空间或系统表空间到通用表空间。
ALTER TABLE tbl_name TABLESPACE [=] tablespace_name
例:修改表从独立表空间到通用表空间
mysql> select
-> name as 'table_name',
-> space_type
-> from
-> information_schema.innodb_tables
-> where
-> name ='testdb/test_file_pertable_tablespace' \g
+--------------------------------------+------------+
| table_name | space_type |
+--------------------------------------+------------+
| testdb/test_file_pertable_tablespace | Single |
+--------------------------------------+------------+
1 row in set (0.00 sec)
mysql> alter table test_file_pertable_tablespace tablespace=test_tbs1;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select
-> name as 'table_name',
-> space_type
-> from
-> information_schema.innodb_tables
-> where
-> name ='testdb/test_file_pertable_tablespace' \g
+--------------------------------------+------------+
| table_name | space_type |
+--------------------------------------+------------+
| testdb/test_file_pertable_tablespace | General |
+--------------------------------------+------------+
1 row in set (0.00 sec)
mysql>
例:修改表从系统表空间到通用表空间
mysql> select
-> name as 'table_name',
-> space_type
-> from
-> information_schema.innodb_tables
-> where
-> name ='testdb/test_file_pertable' \g
+---------------------------+------------+
| table_name | space_type |
+---------------------------+------------+
| testdb/test_file_pertable | System |
+---------------------------+------------+
1 row in set (0.01 sec)
mysql> alter table test_file_pertable tablespace=test_tbs1;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select
-> name as 'table_name',
-> space_type
-> from
-> information_schema.innodb_tables
-> where
-> name ='testdb/test_file_pertable' \g
+---------------------------+------------+
| table_name | space_type |
+---------------------------+------------+
| testdb/test_file_pertable | General |
+---------------------------+------------+
1 row in set (0.00 sec)
mysql>
例2-3:修改表从通用表空间或系统表空间到独立表空间
可以通过如下命令修改表从通用表空间或系统表空间到独立表空间。
ALTER TABLE tbl_name TABLESPACE [=] innodb_file_per_table;
例:修改表从通用表空间到独立表空间
mysql> select
-> name as 'table_name',
-> space_type
-> from
-> information_schema.innodb_tables
-> where
-> name ='testdb/test_file_pertable' \g
+---------------------------+------------+
| table_name | space_type |
+---------------------------+------------+
| testdb/test_file_pertable | General |
+---------------------------+------------+
1 row in set (0.00 sec)
mysql> alter table test_file_pertable tablespace=innodb_file_per_table;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select
-> name as 'table_name',
-> space_type
-> from
-> information_schema.innodb_tables
-> where
-> name ='testdb/test_file_pertable' \g
+---------------------------+------------+
| table_name | space_type |
+---------------------------+------------+
| testdb/test_file_pertable | Single |
+---------------------------+------------+
1 row in set (0.01 sec)
mysql>
例2-4:修改表从通用表空间或独立表空间到系统表空间
可以通过如下命令修改表从通用表空间或独立表空间到系统表空间。
ALTER TABLE tbl_name TABLESPACE [=] innodb_system;
例:修改表从独立表空间到系统表空间
mysql> select
-> name as 'table_name',
-> space_type
-> from
-> information_schema.innodb_tables
-> where
-> name ='testdb/test_file_pertable' \g
+---------------------------+------------+
| table_name | space_type |
+---------------------------+------------+
| testdb/test_file_pertable | Single |
+---------------------------+------------+
1 row in set (0.00 sec)
mysql>
mysql> alter table test_file_pertable tablespace=innodb_system;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> select
-> name as 'table_name',
-> space_type
-> from
-> information_schema.innodb_tables
-> where
-> name ='testdb/test_file_pertable' \g
+---------------------------+------------+
| table_name | space_type |
+---------------------------+------------+
| testdb/test_file_pertable | System |
+---------------------------+------------+
1 row in set (0.00 sec)
参考
15.6.3.3 General Tablespaces
https://dev.mysql.com/doc/refman/8.0/en/general-tablespaces.html
13.1.21 CREATE TABLESPACE Statement
https://dev.mysql.com/doc/refman/8.0/en/create-tablespace.html
Chapter 2 Server Error Message Reference
https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html
Error number: 3121; Symbol: ER_WRONG_FILE_NAME; SQLSTATE: HY000
Message: Incorrect File Name ‘%s’.