四、如何正确的减少磁盘文件
在第三小节中,我们演示了删除了100W数据后文件大小是没有改变的,也就是空洞问题影响的,接下来就解决这种问题。
问题:空洞是如何产生的?
到了这里都应该知道空洞是因为大量的增删改造成的。
解决思路
你可以新建一个evt_sms_copy表,然后根据主键ID递增的顺序,把数据从evt_sms读入evt_sms1中。
这样就可以达到因为空洞造成的磁盘文件大小无法收缩问题。
问题:为什么能解决呢?
因为evt_sms_copy是一张新的表,并且数据是以主键ID递增的,索引是紧促的,数据页利用率已经达到了最高峰状态,这样就起到了磁盘文件无法收缩问题。
上干货
直接执行alter table evt_sms engine = Innodb 命令来达到磁盘文件收缩。
这里需要跟大家聊一下不同版本处理不同。
在MySQL5.5之前,这个命令做的事情跟我们解决思路是一样的,不同的是evt_sms_copy是不用自己创建的。
在执行命令期间如有新增数据的话,会造成数据丢失,因为在MySQL5.5之前版本的DDL不是Online的。因此不能有数据的改动。
现在MySQL都已经更新到8版本了,如果你是新项目就直接用8版本,不要在用5.6以前的老版本了,咔咔在18年开始就已经在使用MySQL8.0版本了。
在锁那一期文章中跟大家聊了MySQL5.6在DDL操作做了优化,引入了Online DDL。
优化后的执行流程
建立临时文件tmp_file,把表的B+树存储到临时文件中。若此时有对表的操作,则会记录在row log文件中。
把数据从原表全部刷到临时文件后,此时临时文件的数据就跟原表的数据一致。
最后用临时文件替换表A的数据文件。
Online DDL的由来
可以看到在收缩磁盘文件时有数据更新会记录在row log中,意思就是在收缩磁盘空间时是可以对表进行增删改查的。
注意点
在进行磁盘文件收缩的过程中,都会全表扫描原数据和新增临时文件,如果你的表非常大,会非常消耗IO和CPU。
因此,你要安全的做这个操作,可以使用开源的gh-ost来进行。
结论
当你想收缩因为大量增删改查而导致表磁盘文件非常大时就可以执行alter table evt_sms engine=Innodb命令来达到收缩表空间的目的。
五、实践是检验认识是否具有真理性的唯一标准
都应该知道实践是检验认识是否具有真理性的唯一标准,那么接下里就对本文提出的结论进行实际操作一下。
- 先执行ctrl + z结束MySQL任务窗口
- 执行ll -h查看此时表evt_sms磁盘文件大小为108M
- 执行fg返回到MySQL任务窗口
- 执行命令alter table evt_sms engine=Innodb
- 再执行ctrl + z,执行ll -h查看磁盘文件大小已经到了128k。
上图即是咔咔操作的全过程,得到的结论就是执行命令alter table ect_sms engine = Innodb可以收缩由于大量增删改查的表引发的空洞问题。最终达到收缩表空间目的。
六、开发建议
删除数据不要使用delete,而是使用软删除,做一个标记删除即可。
这样既不会出现空洞问题,也方便数据溯源。
每张表必备三个字段create_time、update_time、delete_time。
七、总结
通过本期文章我们需要知道以下几点。
- 通过大量增删改查的表会出现空洞
- 干掉空洞需要执行alter table evt_sms engine=Innodb来解决
- 使用delete删除数据只会做一个标记处理,并不会真正删除空间
- 本文所有的结论都基于innodb_file_per_table = on