本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
话说有一天,我心血来潮。登录阿里云,发现 RDS 占用的空间挺大的。想起有一张表,当初设计的不好,没用的数据挺多的。就想着删除清理一部分数据,节约空间。
说做就做,一条 delete 语句,如下:
delete FROM xttblog where day < 2019 and status = 7;
没想到意外发生了,删除几十万条数据后,我再去查看 RDS 占用的数据空间,不仅没降,还上升了。这是怎么回事?
这个问题可能很多人都没有注意到。平时大家的关注点可能都不在这方面。
我把这个数据删除后,阿里云立马发邮件报警,说我们的 RDS 存储空间过大,没办法,当初知识水平有限。就又花公司的钱,升级了存储空间。
这个问题一直困惑着我,直到两年前看了《高性能MySQL》。而今天刚好又有一个网友私信我,我想起了这件事。所以,今天就给大家解惑一下,为什么会这样。
第一个就是网上很多人所说的那样,这是一个MySQL的BUG,直到MySQL 5.7 版本才解决。由于我们当初选的是 MySQL 5.6 的版本,出现这个问题后,也咨询了阿里云。但是阿里云给出的答复是只能进行数据迁移,虽然MySQL5.7版本,可以解决这个问题,但是阿里云的MySQL5.6的版本并不能直接升级到5.7。而迁移数据库也太浪费时间和精力了,搞不好,再把主要数据给丢失了。BOSS 非剁了我不可。
第二个我要说的就是 MySQL 5.6中默认是独立表空间,如果采用独立表存储模式,data 中还会产生 report_site_day.ibd 这类文件(存储数据信息和索引信息)。而删除的时候,它不会被删除。
第三个就是 MySQL 对于删除的功能的底层实现,并不是大家想象的那样,执行 delete 就真的给删除了。而是当你使用 delete 删除的时候,MySQL 并没有把数据文件删除,而是将数据文件的标识位删除,没有整理文件,因此不会彻底释放空间。被删除的数据将会被保存在一个链接清单中,当有新数据写入的时候,MySQL 会利用这些已删除的空间再写入。即,删除操作会带来一些数据碎片,正是这些碎片在占用硬盘空间。
关于数据迁移也会带来一些问题,这个我们下一章再说。今天我先说一下,MySQL 官方推荐的 OPTIMIZE TABLE 命令来清理优化表 InnoDB 空间的做法。
OPTIMIZE TABLE 命令的格式如下:
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
具体的用法如下:
-- OPTIMIZE TABLE 数据库表名;
OPTIMIZE TABLE xtt.xttblog;
或者,你也可以这样批量生成优化所有表的 SQL,再复制出来执行:
SET group_concat_max_len=200000;
SELECT GROUP_CONCAT('OPTIMIZE TABLE ',TABLE_NAME SEPARATOR ';') FROM
information_schema.TABLES WHERE TABLE_SCHEMA=SCHEMA();
除此之外,我们还还可以把表设置为单表存储的形式,这样每个表中的数据单独存储,在删除数据的时候,会随着数据的删除而释放存储空间。
set global innodb_file_per_table = on
至于数据迁移,我们可以先备份后删除然后进行导入。
mysqldump -uxttblog -p123456 --all-databases > db.sql
service mysql stop
rm ibdata
rm ×log文件
service mysql start
mysql -uxttblog -p123456 < db.sql
数据迁移也有很多坑,这也是我下一章想讲的。我们的约定,明天见!
最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!
本文原文出处:业余草: » 走狗屎运了,MySQL占用空间竟然越删越大