03 November 2023

负责的的一个系统中有一张大表,目前来看已经260GB,其实表里的数据因为合规的需要已经删除一半左右。但是mysql的机制问题,虽然数据库删除了,但是这部分空间并没有被回收。目前磁盘可用只剩下20%,趁着最近一次系统暂停升级打算对数据库磁盘进行回收

网上查了相关资料,发现针对这种delete的数据进行空间回收基本有以下几种方式:

  • 1,使用optimize table 命令来整理数据碎片,回收可用的空间
  • 2,使用create table new_table select * from old_table
  • 3,通过alter table的方式来回收空间,例如alter table table_name engine=’InnoDB’

查了一圈资料,发现这三种方法没有明显的优劣对比。于是打算使用个人认为“最正统”的方式optimize table来进行空间回收。考虑到操作过程会对表造成锁表等影响,因此决定将这个表更改下名字后再操作。同时创建一个新表以备业务恢复后需要。虽然其他同事说业务恢复预计要很久,应该有充足的时间进行空间回收。但是你懂的,咱们程序员的话,永远不要百分之百信任。而且后面事实证明我得想法没错哈啊哈😂。 以下是操作过程:

  • 18:00计划停止服务
  • 18:20真正停止服务
  • 18:30执行操作:
    alter table t_invoke rename t_invoke_bak;
    create table t_invoke ...
    
  • 18:50 系统有进件,哎,我擦,不是说停止服务要好几个小时嘛,我这个操作预估也需要两三个小时呢。幸亏机智如我有所准备。
  • 21:00 磁盘从整理之前的80%升到93%了。运维告警已经一大片了,虽然提前告知相关人员,回收过程会造成磁盘占用率升高。但是眼看着磁盘一点点飙高。大家还是有点忐忑的。
  • 21:10 终于执行完毕,磁盘使用率将回到63%
  • 21:15 将表恢复回去,执行下面语句的时候虽然很快,但是还是要找业务空挡的时候执行,否则业务表t_invoke表删掉还没有重建的时候正好应用有读写就麻烦了。
    insert into t_invoke_bak select * from t_invoke ;
    drop table t_invoke;
    alter table t_invoke_bak rename t_invoke;
    

总结

  • 总计2小时40分钟,将一个表260GB的表进行整理,最终将该表的大小缩减到130GB,刚好缩减一半。
  • 这类回收还是要在磁盘空间足够的前提下执行




blog comments powered by Disqus
Fork me on GitHub