从5.7.6开始,增加了一种新的 tablespace模式(成为general tablespace),实际上它和共享表空间比较类似:创建一个单独的ibd,ibd中包含多个表,兼容不同的格式。general tablespace没有库的概念,因此可以在多个库里建属于同一tablespace的表。
为了支持这TABLESPACE,主要做了两部分改动:Innodb层的支持,及Server层对MDL子模块的改动。
下面我们逐一从如何使用,及具体实现的角度来介绍这一新特性
创建tablespace
语法如下:
CREATE TABLESPACE tablespace_name
ADD DATAFILE 'file_name
'
[FILE_BLOCK_SIZE = value]
[ENGINE [=] engine_name
]
例如:
CREATE TABLESPACE myspace ADD DATAFILE ‘zwx.ibd’ FILE_BLOCK_SIZE=8192 ENGINE=INNODB;
file_name需要指定一个ibd后缀的文件,可以是相对路径,也可以是绝对路径,默认在data目录下
FILE_BLOCK_SIZE默认为innodb page size的大小(16kb),当你指定一个值时,例如8192,意味着你需要使用这个表空间来存储压缩表。否则就会报错:
root@sb1 09:22:19>CREATE TABLE t1 (a INT) TABLESPACE=myspace;
ERROR 1478 (HY000): InnoDB: Tablespace `myspace` uses block size 8192 and cannot contain a table with physical page size 16384
root@sb1 09:22:23>CREATE TABLE t1 (a INT) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE = 4 TABLESPACE=myspace;
ERROR 1478 (HY000): InnoDB: Tablespace `myspace` uses block size 8192 and cannot contain a table with physical page size 4096
root@sb1 09:23:15>CREATE TABLE t1 (a INT) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE = 8 TABLESPACE=myspace;
Query OK, 0 rows affected (0.00 sec)
将一个已经存在的表导入到指定tablespace中:
root@sb1 09:33:01>create table t2 (a int) key_block_size=8;
Query OK, 0 rows affected (0.00 sec)
root@sb1 09:33:08>alter table t2 tablespace=myspace;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
从一个general tablespace迁移到系统表空间
root@sb1 09:35:12>CREATE TABLESPACE myspace2 ADD DATAFILE ‘zwx2.ibd’ ENGINE=INNODB;
Query OK, 0 rows affected (0.00 sec)
root@sb1 09:36:42>CREATE TABLE t2(a INT);
Query OK, 0 rows affected (0.00 sec)
root@sb1 09:36:43>ALTER TABLE t2 TABLESPACE=myspace2;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
root@sb1 09:37:25>ALTER TABLE t2 TABLESPACE=innodb_system;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
从tablespace中再移除到独立表空间:
root@sb1 09:37:31>ALTER TABLE t2 TABLESPACE=innodb_file_per_table;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
你可以从INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES表中找到你定义的table space及表
Note:
1. tablespace_name是大小写敏感的,不允许出现’/‘或者innodb_前缀的命名
2. 不支持临时tablespace,也不支持在其中创建临时表
3.在DROP TABLESPACE之前,需要先手动删光里面的表
4.属于tablespace中的表,不支持alter table…import/discard tablespace
5.ALTER TABLE…TABLESPACE总是会触发表的重建, 也不支持修改数据目录
更具体的参考官方文档:
功能实现
由于目前5.7还处于开发中,不排除下面提到的代码函数以后会发生变化。
本文代码参考的是MySQL5.7.6
0.代码修改主要包括底层的代码重构:
和具体实现:http://dev.mysql.com/worklog/task/?id=6205
以及Server层MDL锁机制:
相关类:
1. MDL锁控制
由于增加了新的表空间定义类型,在上层的MDL锁逻辑上也需要做相应的修改,以适应对TABLESPACE的并发访问控制。
需要加TABLESPACE MDL锁的操作:CREATE/ALTER/DROP TABLESPACE 以及对存储在TABLESPACE中的表做DDL
MDL的KEY值:key值即为tablespace的名字, ref: tablespace_set_get_key
新增MDL锁类型:MDL_key::TABLESPACE
CREATE/DROP TABLESPACE: 调用函数lock_tablespace_name加MDL锁,类型为排他锁:MDL_EXCLUSIVE
向SPACESPACE中创建新表/or对表DDL:对tablespace加MDL_INTENTION_EXCLUSIVE锁, ref : lock_table_names,有非常详细的加锁逻辑注释。
DMLtablespace中的表不加tablespace的mdl锁
2. 创建/删除的TABLESPACE(以下只考虑Innodb层堆栈)
相关堆栈
mysql_execute_command –> mysql_alter_tablespace
|–>innobase_alter_tablespace
|–> 创建tablespace: innobase_create_tablespace
// 合法性检查:validate_create_tablespace_info,例如tablespace命名是否已存在(server层无相关信息),相关选项的合法性
// 根据CREATE TABLESPACE时指定的datafile,在内存构建ibd文件路径,加入到tablespace对象中:Tablespace::add_datafile
|–>dict_build_tablespace
// 创建ibd文件: fil_ibd_create
// 更新系统表SYS_TABLESPACES 和 SYS_DATAFILES:dict_replace_tablespace_and_filepath
// 初始化文件头:fsp_header_init
|–> 删除tablespace: innobase_drop_tablespace
// 判断tablespace有效性:validate_tablespace_name
// 只有tablespace中没有表时才允许删除:dict_tablespace_is_empty
// 更新系统表:dict_delete_tablespace_and_datafiles
// 删除数据文件: fil_delete_tablespace
3. 在tablespace中创建表
ha_innobase::create
// 确定创建的表类型是否是file-per-table
// 预检查创建选项,例如指定的tablespace是否存在: create_table_info_t::prepare_create_table
// 创建表的主逻辑: create_table_info_t::create_table
4. 在tablespace间迁移表
可以通过标准ALTER TABLE语句将表从一个tablespace迁移到另外一个tablespace。
数据迁移会产生表数据重建
本文只是简单的过了下相关的概念,更具体的代码修改,可以参考如下:
git show c71dd213bd434c0579e454ab8880e6d3756b0fb0