MySQL|空间碎片化问题处理
1.1 问题描述
实例磁盘空间近1个月上涨趋势明显,主要是个别日志表存储较大且部分表存在空间碎片化的现象。
1.2 处理流程
1、通过日常巡检以及监控发现某实例磁盘空间近1月上涨趋势明显
2、在询问业务方是否为正常的业务增长外,查看该实例top表空间的表,排查是否存在异常较大的表
1)查看数据存储量较大的schema
SELECT table_Schema , round(SUM((DATA_LENGTH + INDEX_LENGTH + DATA_FREE) / 1024 / 1024), 2) AS Total_SizeFROM tablesGROUP BY table_schemaORDER BY Total_Size DESC;
2)查看具体schema下top表的空间使用情况
SELECT table_schema, table_name , round(DATA_LENGTH / 1024 / 1024, 2) AS Data_Size , round(INDEX_LENGTH / 1024 / 1024, 2) AS Index_Size , round(DATA_FREE / 1024 / 1024, 2) AS Free_SizeFROM tablesWHERE table_schema = 'db_rim'ORDER BY Data_Size DESCLIMIT 10;
3、从以上截图中我们可以得到信息:db_rim库库下,rim_user_msg_log表的数据量很大,可查看是否可对该表中无效的数据进行清理?rim_user_msg_analyse这张表的碎片化将尽17G,可考虑对这些碎片化空间进行回收
4、最终采取的处理方法为:rim_user_msg_log表直接清空,rim_user_msg_analyse进行碎片化回收
1)清理前
2)清理后
3)实例磁盘空间使用趋势
二、表数据量过大清理案例
2.1 问题描述
通过对TOP表数据量的监控,我们可以看到sys_rest_server_log的数据量已经达到7000w,除空间占用外,我们更关注的是该表对数据库带来的性能隐患。若业务上或者人为不当的查询该表数据,其操作的资源消耗在一定程度上一定会对正常业务造成影响。
2.2 问题处理
1、该表当前的表现主要有两点,一点是某瞬时写入量极大,另外一点是表日增可达到300w记录数。对于数据库而言这种表行为或业务设计是不合理的,我们需要搞清楚该表究竟是用来记录哪些信息,业务设计是否合理?
通过观察表数据以及与相关开发人员沟通,我们得知该表会记录应用端所有的接口调用信息,我们所观察到的数据增长尖峰也正是由于业务量上涨而导致该表瞬间并发写入大量日志信息。
2、对于这种大数据量的日志记录信息,建议最好使用ELK这种日志分析服务,而不是使用数据库进行存储
3、限于开发人员开发能力有限,无法改造业务架构。针对该表日增长、瞬间增长都极大的情况,我们与开发人员沟通该表记录的数据是否可从源端上进行减少。只记录重要信息、非重要信息的接口日志入库进行屏蔽
4、确定表数据记录可从最根本减产后,我们仍需要对目前7000w的数据进行处理,将历史无效数据进行清理,并制定合适的数据清理策略
5、无效历史数据清理/数据清理策略
1、创建备份表:create table sys_rest_server_log_bak_0228_1 like sys_rest_server_log;2、表名替换将源表sys_rest_server_log重命名为备份表,备份表sys_rest_server_log_bak_0208_1重命名为源表sys_rest_server_log,业务数据会写入空的新表,但是在rename期间这部分业务日志写入会失败【需关注】rename table sys_rest_server_log to sys_rest_server_log_bak_0228_2,sys_rest_server_log_bak_0228_1 to sys_rest_server_log;3、将备份表sys_rest_server_log_bak_0208_2中的仍然需要的数据重新写入到sys_rest_server_log,分批次写入,sys_rest_server_log保留近15天数据。程序上可保证主键fd_id唯一,避免主键冲突。insert into sys_rest_server_log select * from sys_rest_server_log_bak_0228_2 where fd_start_time between 'xxx' and 'xxx';4、调整平台数据清理策略,将服务运行日志备份天数改为15天,清除服务运行日志备份天数改为30天5、sys_rest_server_log_bak_0228_2表保留80+天记录数据,暂时可以不做清理,等程序维护的sys_rest_server_log_backup有完备的数据后,将sys_rest_server_log_bak_0228_2表清除;
三、总结归纳
2.1 如何判断表碎片化问题是否严重
表数据的频繁更新容易对表空间造成一定的碎片化,我们可以通过information_schema.table表中的data_free字段判断该表碎片化是否严重。
2.2 如何处理碎片化问题
optimize table tableName;alter table tablName engine=innodb;
2.3 大表历史数据清楚过程中的关注点
1、通过创建bak表与源表进行rename替换,rename期间会造成业务对该表数据写入失败2、bak表创建的时需关注primayr key 1)程序上保证主键唯一可不需要关注 2)若主键使用自增长,建议在创建bak表创建时提高当前的auto_increment指,空余一部分buffer空间,保证后续将源表历史数据写入rename后的新表时主键不冲突3、对于此类经常需要进行数据清理的表,建议使用分区表进行存储,后续对数据的处理仅仅需要删除指定分区