我有一个亚马逊(AWS)AuroraDB 集群,并且每天都[Billed] Volume Bytes Used
在增加。
我已经使用下表检查了所有表(该集群上的所有数据库中)的大小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 |
+------------+-------------+------------+
总计:53GB
那么为什么我此时要支付近 75GB 的费用呢?
我理解预置空间永远无法释放,就像常规 MySQL 服务器上的 ibdata 文件永远无法缩小一样;我对此没有异议。这是有记录的,也是可以接受的。
我的问题是,每天我所占用的空间都在增加。而且我确定我暂时不会使用 75GB 的空间。如果我要这样做,我会理解。就好像我通过从表中删除行、删除表甚至删除数据库而释放的存储空间永远不会被重新使用一样。
我多次联系 AWS(高级)支持,但始终无法得到很好的解释。我收到的建议是,在有大量数据(每个表)的表上
运行,或者检查 InnoDB 历史记录长度,以确保已删除的数据不会仍保留在回滚段中(参考:OPTIMIZE TABLE
free_space
INFORMATION_SCHEMA.TABLES
脉动循环控制电路),然后重新启动实例以确保回滚段已清空。
这些都无济于事。
答案1
这里有多件事在起作用……
每个表都存储在自己的表空间中
默认情况下,Aurora 集群(名为)的参数组
default.aurora5.6
定义innodb_file_per_table = ON
。这意味着每个表都存储在 Aurora 存储集群上的单独文件中。您可以使用此查询查看每个表使用的表空间:SELECT name, space FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES;
注意:我还没有尝试过更改
innodb_file_per_table
为OFF
。也许那会有帮助..?删除表空间释放的存储空间不会被重新使用
引用 AWS 高级支持:
由于 Aurora 存储引擎的独特设计,为了提高其性能和容错能力,Aurora 不具备像标准 MySQL 那样对每个表的文件表空间进行碎片整理的功能。
不幸的是,目前 Aurora 无法像标准 MySQL 那样缩小表空间,并且所有碎片空间都会被收费,因为它包含在 VolumeBytesUsed 中。Aurora 无法
像标准 MySQL 那样回收已删除表的空间,原因是表数据的存储方式与具有单个存储卷的标准 MySQL 数据库完全不同。由于设计复杂,如果您在 Aurora 中删除表或行,则不会在 Aurora 集群卷上回收空间。
无法回收少量存储空间是为了获得 Aurora 集群存储卷的额外性能提升和 Aurora 容错能力的极大提高而做出的牺牲。但是有一些不太明显的方法可以重新利用那些浪费的空间...
再次引用 AWS 高级支持的话:一旦您的总数据集超过一定大小(大约 160 GB),您就可以开始以 160 GB 的块形式回收空间以供重复使用,例如,如果您的 Aurora 集群卷中有 400 GB,并且删除了 160 GB 或更多的表,Aurora 就可以自动重新使用 160 GB 的数据。但是回收这些空间可能会很慢。
需要一次释放大量数据的原因是由于 Auroras 的独特设计,它是企业级数据库引擎,而标准 MySQL 不能在这种规模上使用。优化表是邪恶的!
由于 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
使用临时表
默认情况下,Aurora 实例的参数组(名为
default.aurora5.6
)定义default_tmp_storage_engine = InnoDB
。这意味着每次我创建TEMPORARY
表时,它都会与我的所有常规的表,在 Aurora 存储集群上。这意味着需要配置新的空间来保存这些表,从而增加总 VolumeBytesUsed。
此问题的解决方案非常简单:将default_tmp_storage_engine
参数值更改为。这将强制 Aurora在实例的本地存储上MyISAM
创建表。 值得注意的是:实例的本地存储是有限的;请查看CloudWatch 上的指标以了解您的实例有多少存储空间。更大(更昂贵)的实例拥有更多的本地存储空间。TEMPORARY
Free Local Storage
参考:尚无;当前的 Amazon Aurora 文档未提及此内容。我已要求 AWS 支持团队更新文档,如果他们更新了,我也会更新我的答案。
答案2
值得庆幸的是,这个问题不会持续太久。AWS 已宣布动态调整存储空间大小: https://aws.amazon.com/about-aws/whats-new/2020/10/amazon-aurora-enables-dynamic-resizing-database-storage-space/
答案3
当删除 Aurora 数据(例如删除表或分区)时,分配的总体空间保持不变。将来数据量增加时,将自动重新使用可用空间。 https://docs.amazonaws.cn/en_us/AmazonRDS/latest/AuroraUserGuide/Aurora.Managing.Performance.html