表空间介绍

共享表空间优缺点

既然Innodb有共享表空间和独立表空间两种类型,那么这两种表空间存在肯定都有时候自己的应用的场景,存在即合理。以下是摘自mysql官方的一些介绍:

共享表空间的优点

表空间可以分成多个文件存放到各个磁盘,所以表也就可以分成多个文件存放在磁盘上,表的大小不受磁盘大小的限制(很多文档描述有点问题)。

数据和文件放在一起方便管理。

共享表空间的缺点

所有的数据和索引存放到一个文件,虽然可以把一个大文件分成多个小文件,但是多个表及索引在表空间中混合存储,当数据量非常大的时候,表做了大量删除操作后表空间中将会有大量的空隙,特别是对于统计分析,对于经常删除操作的这类应用最不适合用共享表空间。

共享表空间分配后不能回缩:当出现临时建索引或是创建一个临时表的操作表空间扩大后,就是删除相关的表也没办法回缩那部分空间了(可以理解为mysql的表空间10G,但是才使用10M,但是操作系统显示mysql的表空间为10G),进行数据库的冷备很慢;

独立表空间的优缺点

独立表空间的优点

每个表都有自已独立的表空间,每个表的数据和索引都会存在自已的表空间中,可以实现单表在不同的数据库中移动。

空间可以回收(除drop table操作处,表空不能自已回收)

Drop table操作自动回收表空间,如果对于统计分析或是日值表,删除大量数据后可以通过:alter table TableName engine=innodb;回缩不用的空间。

对于使innodb-plugin的Innodb使用turncate table也会使空间收缩。

对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。

独立表空间的缺点

单表增加过大,当单表占用空间过大时,存储空间不足,只能从操作系统层面思考解决方法

共享表空间存的那些数据?

1.系统数据

2.undo

3.临时表

#查看表空间
mysql> show variables like '%path%';
+-----------------------+------------------------+
| Variable_name         | Value                  |
+-----------------------+------------------------+
| innodb_data_file_path | ibdata1:12M:autoextend |
| ssl_capath            |                        |
| ssl_crlpath           |                        |
+-----------------------+------------------------+

独立表空间

#查看独立表空间是否开启
mysql> show variables like '%per_table%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+

[root@db02 test1]# ll /data/test1/
total 236
-rw-rw---- 1 mysql mysql     61 Jun 17 15:43 db.opt  
-rw-rw---- 1 mysql mysql   8586 Jun 23 15:21 t1.frm  #表结构
-rw-rw---- 1 mysql mysql  98304 Jun 23 17:49 t1.ibd  #独立表空间
-rw-rw---- 1 mysql mysql   8622 Jun 23 17:32 t2.frm
-rw-rw---- 1 mysql mysql 114688 Jun 23 17:49 t2.ibd


企业实例(模拟表空间损坏)

mysql3307中test1库中t1,t2表空间损坏
mysql> show tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| t1              |
| t2              |
+-----------------+
2 rows in set (0.00 sec)
mysql> select * from t1;
ERROR 1146 (42S02): Table 'test1.t1' doesn't exist '

#准备一个新的数据库mysql3308 
进入3308创建一个相同的库
mysql>create datebase test1;
mysql>use test1;
#找到当初建表时的sql语句 *****
mysql> CREATE TABLE `t1` (
->   `id` int(11) NOT NULL AUTO_INCREMENT,
->   `name` varchar(20) DEFAULT NULL,
->   PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE `t2` (
->   `id` int(11) NOT NULL AUTO_INCREMENT,
->   `score` tinyint(4) DEFAULT NULL,
->   `stu_id` int(11) DEFAULT NULL,
->   PRIMARY KEY (`id`),
->   KEY `stu_fk` (`stu_id`),
->   CONSTRAINT `stu_fk` FOREIGN KEY (`stu_id`) REFERENCES `t1`(`id`) ON DELETE CASCADE ON UPDATE CASCADE  
-> ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)
#如果有外键先创建时先不添加外键 或者创建完成后删除外键 alter table t2 drop foreign key stu_fk;

#删掉新建t1,t2的表空间文件
mysql> alter table test1.t1 discard tablespace;
Query OK, 0 rows affected (0.00 sec)

mysql> alter table test1.t2 discard tablespace;
Query OK, 0 rows affected (0.00 sec)

#确认已删除表空间文件
[root@db02 data]# ll /data3308/data/test1
total 28
-rw-rw---- 1 mysql mysql   65 Jun 23 22:49 db.opt
-rw-rw---- 1 mysql mysql 8586 Jun 23 22:55 t1.frm
-rw-rw---- 1 mysql mysql 8622 Jun 23 23:06 t2.frm

#拷贝mysql3307下的t1,t2表空间文件到3308中
[[root@db02 data]# cp -a /data3307/data/test1/t{1,2}.ibd /data3308/data/test1/
[root@db02 data]# ll /data3308/data/test1/
total 236
-rw-rw---- 1 mysql mysql     65 Jun 23 22:49 db.opt
-rw-rw---- 1 mysql mysql   8586 Jun 23 22:55 t1.frm
-rw-r----- 1 mysql mysql  98304 Jun 23 22:41 t1.ibd
-rw-rw---- 1 mysql mysql   8622 Jun 23 23:06 t2.frm
-rw-r----- 1 mysql mysql 114688 Jun 23 22:41 t2.ibd

#mysql3308中导入表空间(一定要导入,否则会提示表空间被丢弃 ERROR 1814 (HY000): Tablespace has been discarded for table 't1')
mysql> alter table t1 import tablespace;
Query OK, 0 rows affected, 1 warning (0.02 sec)

mysql> alter table t2 import tablespace;
Query OK, 0 rows affected, 1 warning (0.01 sec)

#恢复外键
mysql> alter table t2 add constraint stu_fk foreign key(stu_id) references t1(id) on delete cascade on update cascade;
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

#查看是否修复
mysql> select * from t1;
+----+--------+
| id | name   |
+----+--------+
|  1 | zhang3 |
|  4 | li4    |
+----+--------+
2 rows in set (0.00 sec)

mysql> select * from t2;
+----+-------+--------+
| id | score | stu_id |
+----+-------+--------+
|  3 |    50 |      1 |
|  4 |    60 |      4 |
+----+-------+--------+
2 rows in set (0.00 sec)

#mysqldump导出数据
mysqldump -uroot -p -S /data3308/data/mysql.sock test1 t1 t2 > tmp/mysql.sql

#删除3307中test1库中t1,t2空表间
[root@db02 data]# cd /data3307/data/test1
[root@db02 test1]# ls
db.opt  t1.ibd  t2.frm  t2.ibd
[root@db02 test1]# 
[root@db02 test1]# rm -f t{1,2}.ibd

#导入表
mysql3307 -uroot -p test1< tmp/mysql.sql 或者
mysql3307 -uroot -p
set sql_log_bin=0 临时关闭binlog
source <tmp/mysql.sql


ps:也可以sed修改/tmp/mysql.sql文件中的库名通过
sed -i -e 's#t1#t1_new#g' -e 's#t2#t2_new#g' tmp/mysql.sql  改名后导入 
再删除掉原来已损坏的表空间,将t1_new和t2_new通过命令 altet table t1_new rename t1  改名为t1,t2