MySQL 表空间碎片的概念及相关问题解决

 更新时间:2021年05月07日 11:53:31   作者:王文安  
这篇文章主要介绍了MySQL 表空间碎片的概念及相关问题解决,帮助大家更好的理解和学习使用MySQL,感兴趣的朋友可以了解下

背景

经常使用 MySQL 的话,会发现 MySQL 数据文件的磁盘空间一般会不停的增长,而且有时候删了数据或者插入一批数据的时候,磁盘空间有时候还会毫无变化。引发这个其妙现象的就是 MySQL 的表空间碎片。

什么是表空间碎片?

表空间碎片指的是表空间中存在碎片,形象一点来比喻的话,就像是一张 A4 纸,“表空间碎片”就像是把这张 A4 纸撕碎,再重新拼起来,各个碎片之间都会有一些缝隙存在,这些缝隙就是“表空间碎片”。重新拼起来的碎片实际上会比完整的 A4 纸大上一圈,这也代表着表空间容易引发的问题:空间浪费。

对于背景中描述的现象,可以用一张图来进行解释:

图中的数字代表真实的数据行,圆角矩形代表一个表的表空间。从左往右,第一次操作是删除数据,由于 MySQL 在设计上是不会主动释放空间的,因此当表中的数据行被删除时,虽然数据被“删除”了,但是实际上这部分空间是没有释放的,依旧会被 Table A 占用,因此也就出现了这样子的情景:删除了日志表的很多数据,但是 MySQL 的磁盘空间并没有降低。

PS:这种不释放空间的设计多半和惰性删除有关,早期设计数据库时,使用的 IO 设备一般是机械盘,读写性能比 SSD 差很多,所以删除操作一般不会直接触发磁盘上的数据删除。

可以看到数据删除之后,原本连续的空间中出现了两个空白的区域,这种一般就叫做表空间空洞,空洞太多了就叫做表空间碎片化(对应的是表空间连续)。这部分的空间虽然不会释放,但是会被标记为可重复利用,参考最右边的表空间示意图(第三个圆角矩形),当新插入数据的时候新数据会重新写入到表空间空洞中,这也代表着:在大规模删除过数据的表上,写入数据时,表空间可能不会明显增长或者不会增长。

实际上产生表空间空洞的操作并不只有 delete,update 也会引起这个问题,比如在 varchar 这种变长的字符型列中修改数据,改短一些的时候就会出现非常小的空洞,改长的话就有可能会因为空间不足导致把数据行的一些数据迁移到其他地方去。

怎么查看表空间碎片

MySQL 的系统表记录了表空间的使用情况,可以用如下查询检查:

SELECT CONCAT(table_schema,'.',table_name) AS 'table_name',
                table_rows AS 'Number of Rows',
                CONCAT(ROUND(data_length/(1024*1024),2),' M') AS 'data_size',
                CONCAT(ROUND(index_length/(1024*1024),2),' M') AS 'index_size' ,
                CONCAT(ROUND(data_free/(1024*1024),2),' M') AS'data_free',
                CONCAT(ROUND(data_free/data_length,2),' %') AS 'data_free_pct',
                ENGINE as 'engine'
FROM information_schema.TABLES
WHERE table_schema = 'tablename' 
ORDER by data_free desc;

data_free 指表空间碎片的总空间大小,data_free_pct 指这个表的碎片百分比,效果如下:

mysql> SELECT CONCAT(table_schema,'.',table_name) AS 'table_name',
    ->                 table_rows AS 'Number of Rows',
    ->                 CONCAT(ROUND(data_length/(1024*1024),2),' M') AS 'data_size',
    ->                 CONCAT(ROUND(index_length/(1024*1024),2),' M') AS 'index_size' ,
    ->                 CONCAT(ROUND(data_free/(1024*1024),2),' M') AS'data_free',
    ->                 CONCAT(ROUND(data_free/data_length,2),' %') AS 'data_free_pct',
    ->                 ENGINE as 'engine'
    -> FROM information_schema.TABLES
    -> WHERE table_schema = 'sbtest'
    -> ORDER by data_free desc;
+----------------+----------------+-----------+------------+-----------+---------------+--------+
| table_name     | Number of Rows | data_size | index_size | data_free | data_free_pct | engine |
+----------------+----------------+-----------+------------+-----------+---------------+--------+
| sbtest.sbtest5 |              0 | 0.02 M    | 0.00 M     | 44.00 M   | 2816.00 %     | InnoDB |
| sbtest.sbtest4 |         986400 | 214.70 M  | 15.52 M    | 4.00 M    | 0.02 %        | InnoDB |
| sbtest.sbtest3 |         986400 | 214.70 M  | 15.52 M    | 4.00 M    | 0.02 %        | InnoDB |
| sbtest.sbtest2 |         986400 | 214.70 M  | 15.52 M    | 4.00 M    | 0.02 %        | InnoDB |
| sbtest.sbtest1 |         987400 | 199.70 M  | 15.52 M    | 4.00 M    | 0.02 %        | InnoDB |
+----------------+----------------+-----------+------------+-----------+---------------+--------+
5 rows in set (0.00 sec)

第一行数据是测试用的数据,表中的所有数据都被删掉了,因此计算出来的 data_free_pct 超过了 100%。

怎么解决表空间碎片问题

目前,能够回收表空间的办法仅有一个,就是重建表,手段包括但不限于 optimize,alter table 等。alter table 的有些操作只能靠 rebuild 表来完成,所以有时候对大表进行一些维护操作之后,也会看到磁盘空间使用率下降,这就是回收了表空间碎片腾出来的那一部分空间。

从一般经验来看,表空间碎片的回收操作不建议经常执行,每个月一次就足够了,因为 rebuild 表对服务器的资源影响会比较大,且会影响这个表的写入操作。碎片率(data_free_pct)低于 20% 的时候也不用特别在意,除非磁盘空间非常紧张,且日志基本被清空。

对于回收空间的问题

对一些日志表,或者是有区域性特征的表,建议使用 MySQL 的分区表来管理,需要清理一批数据的时候,可以用 partition truncate 的方式进行清理,磁盘空间也能直接释放掉。

以上就是MySQL 表空间碎片的概念及相关问题解决的详细内容,更多关于MySQL 表空间碎片的资料请关注脚本之家其它相关文章!

相关文章

  • 详解MySQL日期 字符串 时间戳互转

    详解MySQL日期 字符串 时间戳互转

    本篇文章主要介绍了详解MySQL日期 字符串 时间戳互转,详解date转字符串、date转时间戳、字符串转date、字符串转时间戳、时间戳转date,时间戳转字符串,有兴趣的可以了解一下。
    2017-01-01
  • mysql存储过程实例

    mysql存储过程实例

    这篇文章主要介绍了mysql存储过程实例,需要的朋友可以参考下
    2014-04-04
  • MySQL 5.7新特性介绍

    MySQL 5.7新特性介绍

    这篇文章主要为大家详细介绍了MySQL 5.7新特性,了解一下MySQL 5.7的部分新功能,需要的朋友可以参考下
    2016-06-06
  • 深入MYSQL字符数字转换的详解

    深入MYSQL字符数字转换的详解

    本篇文章是对MYSQL中的字符数字转换进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • mysql socket文件作用详解

    mysql socket文件作用详解

    这篇文章主要介绍了mysql socket文件作用的相关资料,需要的朋友可以参考下
    2016-09-09
  • MySQL查询语句大全集锦

    MySQL查询语句大全集锦

    这篇文章主要介绍了MySQL查询语句大全集锦,需要的朋友可以参考下
    2016-06-06
  • mysql数据库备份命令分享(mysql压缩数据库备份)

    mysql数据库备份命令分享(mysql压缩数据库备份)

    这篇文章主要介绍了mysql数据库备份常用语句,包括数据库压缩备份、备份多个MySQL数据库、备份多个MySQL数据库、将数据库转移到新服务器等语句
    2014-01-01
  • MySQL系列之五 视图、存储函数、存储过程、触发器

    MySQL系列之五 视图、存储函数、存储过程、触发器

    视图就是一条select语句执行后返回的结果集;触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合;函数存储着一系列sql语句,调用函数就是一次性执行这些语句,而存储过程就是一组可编程的函数,需要的朋友可以参考下
    2021-07-07
  • Python版Mysql爆破小脚本

    Python版Mysql爆破小脚本

    本文给大家分享的是使用Python制作的MySQL在线用户密码的暴力破解脚本,非常的好用,有需要的小伙伴可以参考下
    2016-10-10
  • MySQL数据类型varchar详解

    MySQL数据类型varchar详解

    这篇文章详细介绍了MySQL数据类型varchar,探讨varchar到底能存多长的数据、InnoDB和MyISAM中的varchar等问题,需要的朋友可以参考下
    2014-03-03

最新评论