表碎片率过高可能导致的问题
场景描述
在使用RDS for MySQL过程中,经常遇到表碎片率过高的问题。表碎片是指在MySQL数据库中,表的数据和索引分散在不同的物理块中,这些物理块可能不连续,或者有一些空闲的空间,从而导致表的数据和索引在磁盘上的存储不是最优的。
这种现象主要是由于MySQL表的数据操作(比如删除、更新、插入等操作)引起的,会使得表中的数据行不断地被修改和移动,从而导致表中的数据片段变得不连续。
影响及风险
排查方法
方法一:通过智能DBA功能实时查看实例磁盘空间使用情况,避免出现磁盘空间不足的问题。
- 登录管理控制台。
- 单击管理控制台左上角的,选择区域。
- 单击页面左上角的,选择“数据库 > 云数据库 RDS”,进入RDS信息页面。
- 在“实例管理”页面,选择目标实例,单击实例名称,进入实例的“概览”页签。
- 在左侧导航栏选择“智能DBA助手 > 实时诊断”。
- 选择“容量预估”页签,页面中的Top50库表空间统计中可以查看碎片空间及碎片率数据。
图1 Top50库表
方法二:通过命令方式查看碎片率数据。
- 使用以下命令对表进行分析,更新表的统计信息。
ANALYZE TABLE table_name;
- 使用以下命令可以查看表的详细信息。
SELECT table_name, data_length, data_free FROM information_schema.tables WHERE table_schema = 'database_name' AND table_name = 'table_name';
- table_name:表名称。
- data_length:表存储的数据大小(单位:字节)。
- data_free:表剩余的空闲空间大小(单位:字节)。
一般来说,可以通过data_free占data_length的比例来初步判断碎片率,估计碎片情况。
原因分析
原因1:DRS全量迁移阶段并行迁移导致
DRS在全量迁移阶段,为了保证迁移性能和传输的稳定性,采用了行级并行的迁移方式。当源端数据紧凑情况下,通过DRS迁移到云上RDS for MySQL后,更高的碎片率可能会导致数据膨胀,使得磁盘空间使用远大于源端。
原因2:大量删除操作后在表空间留下碎片
当删除数据时,MySQL并不会回收被删除数据占据的存储空间,而只做标记删除,尝试供后续复用,等新的数据来填补相应空间,如果没有数据来及时填补这些空间,就造成了表空间膨胀,形成大量碎片。
可以通过如下SQL语句,查询某个表的详细信息,回显中的“DATA_FREE”字段表示表空间碎片大小。
select * from information_schema.tables where table_schema='db_name' and table_name = 'table_name'\G;
解决方案
以下场景可能需要优化表碎片率:
- 数据库长时间运行。
- 大量数据变更
- 数据库性能下降
- 磁盘空间不足
针对表碎片率过高的问题,建议定期对频繁访问的表做碎片分析并清理碎片,进行表空间优化整理,从而缩小空间,优化性能。
执行如下命令对表进行分析:
OPTIMIZE TABLE table_name;
optimize table命令会有短暂锁表操作,整体执行时间与表大小有关。一般执行时间较长,且较为占用资源(必须预留被optimize表1.5倍大小的磁盘空间),所以进行表空间优化时建议避开业务高峰期,避免影响正常业务的进行。