某天公司腾讯云CDB服务器磁盘空间占用很高,而我们自己查看数据+索引则不多。原来我们日常定时删除操作delete并末释放磁盘空间。
使用delete删除的时候,mysql并没有把数据文件删除,而是将数据文件的标识位删除,没有整理文件,因此不会彻底释放空间。被删除的数据将会被保存在一个链接清单中,当有新数据写入的时候,mysql会利用这些已删除的空间再写入。即,删除操作会带来一些数据碎片,正是这些碎片在占用硬盘空间。(BTW:看官方文档上好像是innodb引擎的可以利用操作系统来帮忙回收这些碎片,MyISam的表没有办法自己回收,这里待定,后续再看下)
查看数据库上所有表的大小,大概能统计出所占空间大小。
mysql> use information_schema;
Database changed
mysql> SELECT TABLE_NAME,concat(round((DATA_LENGTH/1024/1024),2),'MB'),concat(round((INDEX_LENGTH/1024/1024),2),'MB') FROM `TABLES` ORDER BY DATA_LENGTH DESC;
+----------------------------------------------------+-----------------------------------------------+------------------------------------------------+
| TABLE_NAME | concat(round((DATA_LENGTH/1024/1024),2),'MB') | concat(round((INDEX_LENGTH/1024/1024),2),'MB') |
+----------------------------------------------------+-----------------------------------------------+------------------------------------------------+
| report_copy | 14729.00MB | 18130.00MB |
| s_num | 11392.00MB | 17689.91MB |
| stat | 5452.00MB | 4741.80MB |
| game_log | 3522.00MB | 6235.95MB |
官方推荐使用 OPTIMIZE TABLE命令来优化表,该命令会重新利用未使用的空间,并整理数据文件的碎片。
语法如下:
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
注:该命令将会整理表数据和相关的索引数据的物理存储空间,用来减少占用的磁盘空间,并提高访问表时候的IO性能。但是,具体对表产生的影响是依赖于表使用的存储引擎的。该命令对视图无效。
该命令目前只对MyISAM、InnoDB,ARCHIVE的表起作用,其余引擎的不起作用
OPTIMIZE 在操作过程中会锁表,50多G数据表锁了将近1个小时,所以这点要特别注意。执行完毕释放了20G左右的空间,还是非常有效果的
-----------------------------------------------------
踩过的坑: optimize 本质是alter table
mysql 5.5 的改表过程如下
1.创建一张新的临时表 tmp
2.把旧表锁住,禁止插入删除,只允许读写 (这就是为什么上面的insert语句都停留在waiting for table metadata lock)
3.把数据不断的从旧表,拷贝到新的临时表,(这就是上面报copy to tmp table)
4.等表拷贝完后,进行瞬间的rename操作
5.旧表删除掉
所以optimize最大的问题是锁表,锁表会导致insert,delete,update语句堵住,确保操作时业务切走。
alter table会复制一个表出来,磁盘空间会增加,操作完成合删除旧表。 这一过程可能会爆磁盘