为什么InnoDB明显提供虚假的自由空间信息

时间:2017-02-21 16:43:48

标签: mysql database innodb

在删除一个相当大的表后,我试图知道我的数据库有多大程度("可用空间")。 (约10GB)

我已经运行了命令:

SELECT table_schema "Data Base Name", 
round( sum( data_free ) / 1024 / 1024 / 1024 ) "Free Space in GB" 
FROM information_schema.TABLES
GROUP BY table_schema;

给了我一个数据库列表,以及他们的#34;空闲空间"。

问题是,根据此报告,已移除10GB表的数据库现在具有1500GB +可用空间,显着大于我的实际硬盘容量。 (大约200GB)

这怎么可能?我怎样才能得到更真实的报道?我错过了什么吗?

更新

作为一项实验,我在此数据库中添加并删除了1GB表,现在报告显示大约110GB的可用空间。我的配置可能有问题,或者这是一个常见问题?

2 个答案:

答案 0 :(得分:3)

(这是回答评论中埋藏的一些问题。)

Misnomer “免费”空间仅包括整个街区,不包括街区内的空余空间以及许多其他细节。

案例1:所有表格都在ibdata1 - SHOW TABLE STATUS(或information_schema的等效查询将显示相同的Data_free值,即ibdata1中有多少空闲。这个空间可以被任何表重用。很难将空间返回给操作系统。

案例2:所有表格均为file_per_table - 现在每个Data_free都指向表格的空间。而SUM()是有意义的。 (ibdata1仍然存在,但它不包含任何真正的表; InnoDB需要很多其他东西。)

案例3:混合 - 如果您在不同时间打开/关闭file_per_table,某些表将位于ibdata1中,有些表将拥有自己的表空间。

案例4:在5.7中创建TABLESPACE - 例如,您可以为每个数据库创建一个表空间。

案例5: PARTITIONed表 - 每个分区都像表一样。

案例6: 8.0 - 即将发生更多变化。

数据库==目录在MySQL的目录树中,每个数据库都可以看作是一个文件系统目录。在该目录中可以看到每个表的一些文件集。 .frm文件包含表定义。如果存在.ibd文件,则使用file_per_table创建表。这可能是发现表是否为file_per_table的最可靠方法。 (8.0将在此处进行重大更改。)

我可以重复使用多少空间?没有好的答案。通常插入一行会在它所属的块中找到空间,而Data_free不会缩小。但是,如果存在块拆分,Data_free可以降低16KB(块大小)或4MB(“扩展区大小” - 或者可能是8MB?)的倍数。此外,随机插入导致BTree块平均约为69%。

更改innodb_file_per_table 在下一个CREATE TABLEALTER TABLE之前无效。然后它只会影响新创建/复制的数据+索引(ibdata1或.ibd)的放置位置。它不会破坏数据。

大表通常有4MB到7MB的Data_free。在计算可添加的行数时,请不要将Data_free计划在该范围之下。

Avg_row_size 应该很有用。但有时它(和行)很难近似。他们的产品(Data_length)总是正确的。所以,这个可能是一个很好的估计“从操作系统获取更多空间之前的行:

(Data_free - 7M) / Avg_row_size

表空间建议:将'big'表放在file_per_table中。将'tiny'表放在ibdata1或特定于数据库的表空间(5.7)中。对不起,没有关于'big'和'tiny'之间分界线的简单推荐。迁移表格是笨拙的:SET global innodb_file_per_table = ...;;登出;登录(拿起全局); ALTER TABLE tbl ENGINE=InnoDB;。它必须是该表的完整副本。

警告:我遗漏了很多细节。)

答案 1 :(得分:1)

听起来好像没有设置 innondb_file_per_table ,因此使用共享表空间。如果是这样,那么您将重复为每个table_schema重新生成全局的“已分配但未使用的”共享空间。