InnoDB表回收空间

当innodb_file_per_table设置为OFF,那么全部数据将被存储在ibdata文件。若是删除一些数据和删除一些表则没有回收未使用的磁盘空间,除了导出表而后再导入的方法来回收表空间大小,除此以外没有任何其余的方法。
当innodb_file_per_table设置为ON时,每一个表中存储的数据和索引在它本身的表空间文件。可是,共享表空间的ibdata1仍然在增加,为何呢?由于ibdata1中依然有:html

(1)data dictionary aka metadata of InnoDB tablesmysql

(2)change buffersql

(3)doublewrite buffer服务器

(4)undo logsapp

更为详细的介绍请各位童鞋阅读此文章
http://www.mysqlperformanceblog.com/2013/08/20/why-is-the-ibdata1-file-continuously-growing-in-mysql/工具

当你删除表中一些记录时,他们只是在磁盘上标记为删除,但空间会由之后能够重复使用,当插入/更新多个行,但它永远不会被回收。
可是,若是设置innodb_file_per_table为ON,即便用独立表空间,那么能够经过在该表运行OPTIMIZE TABLE回收空间。 OPTIMIZE TABLE将建立一个新的相同的空表。而后,它会经过行数据复制一行从旧表到新的表。在这个过程当中一个新的。 ibd表空间将被建立和空间将被回收。性能

具体的咱们来看一个例子:优化

mysql> select count(*) from salaries;
+----------+
| count(*) |
+----------+
|  2844047 |
+----------+
1 row in set (0.00 sec)

mysql> 
[root@localhost ~]# ls -lh /data/mysql/employees/salaries.ibd 
-rw-rw---- 1 mysql mysql 140M Mar 26 22:12 /data/mysql/employees/salaries.ibd
[root@localhost ~]# 
mysql> delete from salaries limit 2000000;        
Query OK, 2000000 rows affected (37.50 sec)

mysql> select count(*) from salaries;     
+----------+
| count(*) |
+----------+
|   844047 |
+----------+
1 row in set (0.13 sec)

mysql> 
[root@localhost ~]# ls -lh /data/mysql/employees/salaries.ibd     
-rw-rw---- 1 mysql mysql 140M Mar 26 23:56 /data/mysql/employees/salaries.ibd
[root@localhost ~]# 

能够看见虽然删除200w记录后,可是ibd文件并无减少,仍是140M。spa

mysql> optimize table salaries;
+--------------------+----------+----------+-------------------------------------------------------------------+
| Table              | Op       | Msg_type | Msg_text                                                          |
+--------------------+----------+----------+-------------------------------------------------------------------+
| employees.salaries | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| employees.salaries | optimize | status   | OK                                                                |
+--------------------+----------+----------+-------------------------------------------------------------------+
2 rows in set (7.89 sec)

mysql> 
[root@localhost ~]# ls -lh /data/mysql/employees/salaries.ibd 
-rw-rw---- 1 mysql mysql 48M Mar 27 00:01 /data/mysql/employees/salaries.ibd
[root@localhost ~]# 

在OPTIMIZE 优化表后,能够回收空间。正如你看到的,salaries.ibd文件的大小减少从140M减少到48M。
我想在这里提一提,在这个过程当中该表将被锁定(Table locked for just Writes),当操做比较大的表时,这会影响性能,数据没法写入。因此,若是不想要锁定表,咱们能够使用Percona的pt-online-schema-change。它能够改变表的存储引擎而且不会锁表。能够使用ALTER TABLE ENGINE=INNODB,这将从新建立表并回收空间。code

mysql> select count(*) from  salaries;
+----------+
| count(*) |
+----------+
|  2844047 |
+----------+
1 row in set (0.00 sec)

mysql> delete from salaries limit 2000000;    
Query OK, 2000000 rows affected (21.88 sec)

mysql> \! ls -lh /data/mysql/employees/salaries.ibd 
-rw-rw---- 1 mysql mysql 140M Mar 27 00:21 /data/mysql/employees/salaries.ibd

接下来使用pt-online-schema-change回收空间:

[root@localhost ~]# pt-online-schema-change --alter "ENGINE=InnoDB" D=employees,t=salaries --execute
Operation, tries, wait:
  copy_rows, 10, 0.25
  create_triggers, 10, 1
  drop_triggers, 10, 1
  swap_tables, 10, 1
  update_foreign_keys, 10, 1
Altering `employees`.`salaries`...
Creating new table...
Created new table employees._salaries_new OK.
Altering new table...
Altered `employees`.`_salaries_new` OK.
2014-03-27T00:24:29 Creating triggers...
2014-03-27T00:24:29 Created triggers OK.
2014-03-27T00:24:29 Copying approximately 843830 rows...
2014-03-27T00:24:41 Copied rows OK.
2014-03-27T00:24:41 Swapping tables...
2014-03-27T00:24:41 Swapped original and new tables OK.
2014-03-27T00:24:41 Dropping old table...
2014-03-27T00:24:41 Dropped old table `employees`.`_salaries_old` OK.
2014-03-27T00:24:41 Dropping triggers...
2014-03-27T00:24:41 Dropped triggers OK.
Successfully altered `employees`.`salaries`.
[root@localhost ~]# ls -lh /data/mysql/employees/salaries.ibd 
-rw-rw---- 1 mysql mysql 48M Mar 27 00:24 /data/mysql/employees/salaries.ibd
[root@localhost ~]# 

能够看见已经成功释放空间。从140M缩小到48M

使用该工具须要注意:

请确保有足够的空间运行pt-online-schema-change,由于它会建立一个包含原始表的大小大体相同的临时表。在主的操做会应用到从服务器!(假如你是主从环境)

 

参考资料:

http://www.mysqlperformanceblog.com/2013/09/25/how-to-reclaim-space-in-innodb-when-innodb_file_per_table-is-on/

http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html

相关文章
相关标签/搜索