为什么我的 Amazon Aurora 集群上的“使用的字节数”总是增加?

Gui*_*eau 13 amazon-web-services amazon-rds

我有一个Amazon (AWS) Aurora数据库集群,并且每天都[Billed] Volume Bytes Used在增加。

VolumeBytesUsed CloudWatch 指标随时间的变化

我已经使用表检查了所有表的大小(在该集群上的所有数据库中)INFORMATION_SCHEMA.TABLES

SELECT ROUND(SUM(data_length)/1024/1024/1024) AS data_in_gb, ROUND(SUM(index_length)/1024/1024/1024) AS index_in_gb, ROUND(SUM(data_free)/1024/1024/1024) AS free_in_gb FROM INFORMATION_SCHEMA.TABLES;
+------------+-------------+------------+
| data_in_gb | index_in_gb | free_in_gb |
+------------+-------------+------------+
| 30         | 4           | 19         |
+------------+-------------+------------+
Run Code Online (Sandbox Code Playgroud)

总计:53GB

那么为什么我此时被计费近 75GB?

我知道配置的空间永远不会被释放,就像常规 MySQL 服务器上的 ibdata 文件永远不会缩小一样;我没问题。这是记录在案的,并且是可以接受的。

我的问题是,每天向我收费的空间都在增加。而且我确定我暂时没有使用 75GB 的空间。如果我做那样的事情,我会理解的。就好像我通过从表中删除行、删除表甚至删除数据库而释放的存储空间从未被重新使用。

我已经多次联系 AWS(高级)支持,但始终无法得到一个很好的解释为什么会这样。
我收到OPTIMIZE TABLE了在有很多free_space(每个INFORMATION_SCHEMA.TABLES表)的表上运行的建议,或者检查 InnoDB 历史长度,以确保已删除的数据不会仍然保留在回滚段中(参考:MVCC) ,并重新启动实例以确保回滚段已清空。
这些都没有帮助。

Gui*_*eau 22

这里有很多东西在起作用......

  1. 每个表都存储在自己的表空间中

    默认情况下,Aurora 集群(名为default.aurora5.6)的参数组定义了innodb_file_per_table = ON. 这意味着每个表都存储在 Aurora 存储集群上的一个单独文件中。您可以使用此查询查看每个表使用哪个表空间:

    SELECT name, space FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES;

    注意:我没有尝试更改innodb_file_per_tableOFF. 也许这会有所帮助..?

  2. 通过删除表空间释放的存储空间不会被重新使用

    引用 AWS 高级支持:

    由于 Aurora 存储引擎的独特设计可提高其性能和容错能力,因此 Aurora 没有以与标准 MySQL 相同的方式对每个表的文件表空间进行碎片整理的功能。

    遗憾的是,目前 Aurora 无法像标准 MySQL 那样缩小表空间,并且所有碎片空间都需要收费,因为它包含在 VolumeBytesUsed 中。
    Aurora 无法以与标准 MySQL 相同的方式回收已删除表的空间的原因是,该表的数据以与具有单个存储卷的标准 MySQL 数据库完全不同的方式存储。

    如果您在 Aurora 中删除表或行,由于这种复杂的设计,因此不会在 Aurora 集群卷上回收空间。
    这种无法回收少量存储空间的情况是为了获得 Aurora 集群存储量的额外性能提升和 Aurora 极大提高的容错性而做出的牺牲。

    但是有一些晦涩的方法可以重用一些浪费的空间......
    再次引用AWS高级支持:

    一旦您的总数据集超过特定大小(大约 160 GB),您就可以开始回收 160 GB 块中的空间以供重复使用,例如,如果您的 Aurora 集群卷中有 400 GB 并且 DROP 160 GB 或更多的表,那么 Aurora 可以自动重复使用 160 GB 的数据。但是,回收此空间可能会很慢。
    需要一次性释放大量数据的原因是 Aurora 作为企业级数据库引擎的独特设计,而标准 MySQL 无法在这种规模上使用。

  3. 优化表是邪恶的!

    由于 Aurora 基于 MySQL 5.6,OPTIMIZE TABLE映射到ALTER TABLE ... FORCE,它重建表以更新索引统计信息并释放聚集索引中未使用的空间。实际上,与 一起innodb_file_per_table = ON,这意味着运行一个OPTIMIZE TABLE会创建一个新的表空间文件,并删除旧的。由于删除表空间文件不会释放它正在使用的存储空间,这意味着OPTIMIZE TABLE总是会导致配置更多的存储空间。哎哟!

    参考:https : //dev.mysql.com/doc/refman/5.6/en/optimize-table.html#optimize-table-innodb-details

  4. 使用临时表

    默认情况下,Aurora 实例(名为default.aurora5.6)的参数组定义了default_tmp_storage_engine = InnoDB. 这意味着每次我创建TEMPORARY表时,它都会与我的所有常规表一起存储在 Aurora 存储集群中。这意味着提供了新空间来保存这些表,从而增加了 VolumeBytesUsed 总数。
    对此的解决方案很简单:将default_tmp_storage_engine参数值更改为MyISAM。这将强制 AuroraTEMPORARY在实例的本地存储上创建表。
    注意:实例的本地存储是有限的;查看Free Local StorageCloudWatch 上的指标,了解您的实例拥有多少存储空间。更大(更昂贵)的实例有更多的本地存储。

    参考:还没有;当前的 Amazon Aurora 文档没有提到这一点。我要求 AWS 支持团队更新文档,如果/一旦他们更新,我将更新我的答案。


小智 6

值得庆幸的是,这不会再成为一个问题。AWS 已宣布动态调整存储空间大小: https://aws.amazon.com/about-aws/whats-new/2020/10/amazon-aurora-enables-dynamic-resizing-database-storage-space/