如果MySQL数据库实例的磁盘空间满,会导致实例变为只读状态,写业务夯住,应用无法对数据库进行写入操作,从而影响业务正常运行。本文介绍查看空间使用情况的方式,以及各种空间问题的原因和解决方案。
查看空间使用情况
您可以在实例管理的基本信息页面查看存储空间和备份空间的使用情况,这里只展示当前的空间使用总量,没有展示各类数据分别占用的磁盘空间信息,也没有空间使用的历史信息。
您还可以在实例详情页面,查看目标实例的磁盘空间使用的历史信息和变化曲线。
Binlog日志文件占用过多
原因及现象:
默认binlog日志是保留7天,如果是在迁移大量数据,实例磁盘空间太小的话,会短时间内产生大量的binlog导致磁盘空间不足。
解决方案:
MySQL Binlog日志文件占用过多,可以在mysql命令行上使用PURGE BINARY LOGS BEFORE '2023-06-26 10:00:00'或者PURGE BINARY LOGS TO 'mysql-bin.010'来临时清理本地binlog日志,释放磁盘空间,或者临时修改实例expire_logs_days参数。
表上的索引太多导致空间不足
原因及现象:
通常表上除了主键索引,还存在二级索引,二级索引越多,整个表空间就越大。
解决方案:
优化数据结构,减少二级索引的数量,合并索引建立联合索引等。
大字段导致空间不足
原因及现象:
如果表结构定义中有blob、text等大字段或很长的varchar字段,也会占用更大的表空间。
解决方案:
优化表数据结构,压缩数据后再插入。
表空间碎片太多导致空间不足
原因及现象:
空闲表空间太多到最后InnoDB表的碎片率高。InnoDB是按页(Page)管理表空间的,如果Page写满记录,然后部分记录又被删除,后续这些删除的记录位置又没有新的记录插入,就会产生很多空闲空间。MySQL 的表在进行了长时间多次 delete 、update 和 insert 后,表空间会出现碎片。定期进行表空间整理,消除碎片可以提高访问表空间的性能。
解决方案:
使用以下命令可以找出表空间中可释放空间超过100M的最大10个表:
mysql> select table_name,round(data_length/1024/1024) as data_length_mb, round(data_free/1024/1024) as data_free_mb
from information_schema.tables where round(data_free/1024/1024) > 100 order by data_free_mb desc limit 10;
+------------+----------------+--------------+
| TABLE_NAME | data_length_mb | data_free_mb |
+------------+----------------+--------------+
| sbtest1 | 232 | 274 |
+------------+----------------+--------------+
1 row in set (0.02 sec)
使用 alter table ... force 进行表空间整理和 OPTIMIZE TABLE tablename命令的作用一样,这个命令适用于 InnoDB , MyISAM 和 ARCHIVE 三种引擎的表。但是对于 InnoDB 的表,不支持 OPTIMIZE TABLE 命令,可以用 alter table sbtest1 engine=innodb 代替 ,在业务低峰期整理表空间。
mysql> OPTIMIZE TABLE sbtest1;
+----------------+----------+----------+-------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+----------------+----------+----------+-------------------------------------------------------------------+
| sbtest.sbtest1 | optimize | note | Table does not support optimize, doing recreate + analyze instead |
| sbtest.sbtest1 | optimize | status | OK |
+----------------+----------+----------+-------------------------------------------------------------------+
2 rows in set (1 min 25.24 sec)
mysql> alter table sbtest1 engine=innodb;
Query OK, 0 rows affected (1 min 3.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
临时表空间过大导致空间不足
原因及现象:
半连接(Semi-join)、去重(distinct)、不走索引的order by等操作,会创建临时表,如果涉及的数据量过多,可能导致临时表空间过大。DDL操作重建表空间时,如果表特别大,创建索引排序时产生的临时文件也会特别大。另外很多online DDL操作是不支持Instant算法而是通过创建新表实现的,DDL执行结束再删除旧表,DDL过程中会同时存在两份表。
解决方案:
可以查看explain执行计划,确认是否包含Using Temporary 。大表DDL需要注意实例的空间是否足够,不足的话请提前扩容磁盘。