ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

阿里云DAS三招应对RDS MySQL存储空间不足

阿里云DAS三招应对RDS MySQL存储空间不足

做阿里云代理商这几年,客户找我处理最多的单子不是“帮我加台服务器”,而是“数据库存储空间又满了,怎么办”。尤其是用了 RDS MySQL 的用户,业务平时跑得好好的,突然某天早上收到磁盘空间告警,再晚几分钟实例就会被锁定成只读,整个业务直接趴窝。这种事你说严重吧,也就是空间不够;你说不严重吧,客户急得能连续打五个电话。更烦人的是,手工清理一次解决两三天,过阵子同样的问题又冒出来。

阿里云 DAS(Database Autonomy Service,数据库自治服务)就是专门治这类“慢性病”的。它把空间分析、自动扩容、SQL 优化这些能力打包在一起,不用我们每天盯着监控面板手动折腾。今天这篇我就从自己的实际处理经验出发,把用 DAS 应对数据库存储空间不足的三招拆开揉碎讲清楚。比较适合正在使用阿里云 RDS、PolarDB,并且被空间告警困扰的开发和运维同学;做代理的朋友也可以直接拿这套思路给客户做技术方案参考。

1. 存储空间不足的常见原因与解决思路

1.1 先别急着扩容,看看空间到底被谁吃掉了

很多人的第一反应是“空间不够就扩容呗”,这话没错,但如果不搞清楚空间是被谁吃掉的,扩再多容量也只是续命,不是治病。以我处理过的客户场景来看,存储空间增长过快的原因通常集中在下面几类:

  • 业务数据持续累积:订单表、流水表、日志表天天写入,只增不删,或者只做标记删除,数据量自然越来越大。
  • binlog 和 redo log 文件堆积:实例开启了 binlog,且保存时间较长,在高并发写入场景下,binlog 归档文件会占用大量磁盘。
  • 临时文件或临时表膨胀:一条大查询或者一个长事务,经常会把排序、JOIN 的中间结果写到临时表,临时表目录爆掉是空间告警里非常典型的一种。
  • 表碎片:InnoDB 表频繁做 UPDATE、DELETE 之后,页中留下大量空洞,逻辑上记录没了,物理空间却还占着。
  • 无主键表、大字段表:没有主键的表在做复制和回滚时开销成倍增加;TEXT、BLOB 这类大字段直接把行平均大小拉高,存储和备份都变得很笨重。

你可以把数据库磁盘想象成一个仓库。业务数据是真正进库的货,binlog 是每天产生的包装垃圾,临时文件是拆箱作业时临时占用的空场地,碎片就是货架搬走后留下的一堆空架子。仓库满了,不光是货太多,也可能是因为垃圾没清、架子没拆。只有把每一项都看清楚,才知道该买仓库还是该搞大扫除。

1.2 DAS 的定位:把空间治理变成“自动驾驶”

以前处理空间问题,我们代理商或者运维会在收到告警之后登录实例,查 disk、查表大小、跑 SQL、删数据,一套流程下来半小时起步。而且每个客户实例的情况都不一样,处理方式很难标准化。后来我慢慢把 DAS 用起来,发现它的思路是让数据库具备“自治”能力:自动发现异常、自动诊断原因、自动给出建议、自动执行部分操作。

DAS 在存储空间治理上主要提供了三类能力:

  • 空间分析:展示实例空间使用趋势、剩余可用空间、表空间排行、增长趋势,帮我们快速定位空间消耗大户。
  • 存储自动扩容:当空间使用率达到阈值时,自动扩大存储容量,避免实例进入只读锁定状态。
  • SQL 洞察和自动优化:识别慢 SQL、全表扫描、临时文件导致的额外空间开销,并给出索引或改写建议,从源头减少空间膨胀。

我常跟客户说,DAS 就像一个二十四小时不用休息的数据库 DBA,它不一定替你做完所有事,但能把最耗时间的观察、诊断、预案工作先做掉。我们后面要聊的“三招”,正好对应这三种能力:第一招用空间分析定位问题,第二招用自动扩容兜底,第三招用清理和优化根治问题。

2. 第一招:用空间分析快速定位空间异常

2.1 空间分析入口与核心指标

在阿里云控制台打开 DAS,左侧菜单找到“空间分析”,选择对应的 RDS 或 PolarDB 实例,就能看到实例存储空间的整体画像。需要注意,首次使用可能要先开通 DAS 服务,实例接入完成后需要一点时间采集基础数据,所以新购实例看不到立刻的图表是正常的。

空间分析页面上最核心的几个指标,我一般习惯按这个表格过一遍:

指标含义判断思路
空间使用率当前存储空间已使用百分比超过 70% 就要关注,超过 85% 就要准备处理
剩余可用空间还能撑多久结合每日增长量推算剩余天数,低于 7 天就该介入
最近一周空间趋势每日空间变化曲线看是平稳增长还是突增,突增大概率有异常任务
每日增长量平均每天新增空间占用如果稳定在固定值,说明有持续写入;如果有尖峰,要找固定任务
表空间排行榜Top 表的占空间情况快速定位单表膨胀,或者认识一下哪些表需要归档
binlog 空间占用日志文件占用大小如果这里占比很高,说明删除策略或者参数配置有问题

多数时候,客户发过来的告警截图只写着“磁盘空间使用率 95%”,没有趋势也没有明细。我自己看空间分析的习惯很简单:先看最近七天的趋势曲线,判断空间瓶颈是长期增长还是突然上涨;再翻表空间排行,找到哪个实例里面的哪张表最“肥”;最后对照 binlog 空间占用,确认是不是日志文件在作祟。

2.2 从告警到定位的实操过程

这里分享一次真实的定位过程。客户说昨晚开始告警,磁盘空间从 78% 一路涨到 96%,业务还没崩,但心里已经慌了。我登录 DAS 空间分析,先看到的是增长曲线在当天凌晨有一个陡峭的上升,不像平时那种匀速增长。然后看表空间排行,发现一个名为operation_log的表空间占用已经接近 30GB,而整个实例磁盘才 100GB。继续看 SQL 洞察,发现凌晨两点有一个定时任务在不停往operation_log批量插入数据,三条 INSERT 语句跑了将近四十分钟。

如果不想在 DAS 页面上慢慢翻,也可以直接连到数据库里跑一段 SQL,快速确认 Top 表:

SELECT table_schema, table_name, engine, ROUND((data_length + index_length) / 1024 / 1024, 2) AS total_mb, table_rows FROM information_schema.tables WHERE table_schema = 'your_db' ORDER BY total_mb DESC LIMIT 10;

不过要提醒一句:information_schema 里显示的表大小是逻辑大小,和 DAS 展示的物理空间占用有一定差距,因为还有碎片、页头开销等因素。所以这个 SQL 更多是帮助我们排出“哪些表是候选大户”,真正的空间判定还是以 DAS 或控制台的空间监控为准。

2.3 容易忽略的坑:日志文件、临时文件和采集延迟

空间分析图里,有时候“表空间”加总并不等于实例磁盘使用量。我第一次用 DAS 的时候也困惑过,明明 Top 表加起来才 30GB,为什么磁盘已经用了 60GB?后来才意识到空间分析页面的“空间分布”里通常还有 binlog、临时文件、undo log、系统文件等大项。遇到空间对不上的情况,优先看 binlog 占用。

此外,DAS 空间分析数据存在采集延迟,通常有几分钟到十几分钟不等的滞后。如果实例已经处于空间告警甚至只读状态,不要等待 DAS 数据刷新,先用控制台实时监控或 SQL 直查确认。真实场景里,实例空间告警基本都是分钟级变化,等数据刷新可能就晚了。

3. 第二招:存储自动扩容,省心又防宕机

3.1 自动扩容的原理与触发逻辑

定位问题是第一步,但在客户业务不能停的前提下,第一步之后必须马上做“兜底动作”。DAS 或 RDS 提供的存储自动扩容功能,核心价值就是让数据库存储空间能在无人干预的情况下,自动往上涨一点,避开“被锁成只读”的最坏情况。

触发逻辑不算复杂:系统持续监控实例的存储空间使用率,当使用率超过你设定的阈值(例如 80%),就会按照你设定好的扩容量自动扩容。扩容过程中会按照一定步长增加存储空间,比如每次增加 10% 或者固定增加 20GB,具体以实例规格和控制台提示为准。扩容期间对业务影响很小,不像清理临时文件那样需要人工命令干预。

这个机制很像手机上的“低电量模式”提醒:手机快没电时自动调整后台应用,而不是等关机了再充电。对数据库来说,最怕的不是空间不够,而是空间不够之后实例直接进入只读状态,所有写业务瞬间停摆。有了自动扩容,至少给后续治理争取了时间。

3.2 在控制台配置自动扩容的完整步骤

我以常见的 RDS MySQL 实例为例,配置路径通常是:控制台进入 RDS 实例详情页,找到“配置变更”或“存储空间自动扩展”,也可以直接在 DAS 控制台对应的实例操作里开启存储自动扩容。具体步骤大致是:

  1. 进入实例的“空间管理”或 DAS 的“存储自动扩容”页面。
  2. 打开自动扩容开关。
  3. 设置触发条件:一般有两个参数,一个是空间使用率阈值,另一个是剩余可用空间阈值,满足任一条件就可能触发。
  4. 设置扩容上限:这是最关键的一步,必须根据业务预算和实例规格设置一个合理的最大值,防止扩容无上限导致成本失控。
  5. 确认计费方式:自动扩容会产生新的存储费用,通常按量计费,可以在产生扩容后按实际使用量付费。

参数怎么选?我给客户配置时,阈值一般会放在 75%~80% 之间。如果阈值设成 95%,看起来很省钱,但触发之后没多久可能再次逼近上限,自动扩容会很频繁,而且一旦扩容过程中有几分钟空间写满,实例还是会被锁。阈值设太低又会过早扩大存储,浪费成本。扩容上限我会按业务半年到一年的增长预估来定,不要贪大。比如当前存储 100GB,每月增长 5GB,未来一年约 60GB,上限设成 200GB 就足够稳妥。

3.3 代理商建议:自动扩容一定要搭配告警

自动扩容不是一劳永逸。即使开了自动扩容,我还是会要求客户在云监控里设置空间告警,例如空间使用率达到 70% 触发“通知”级别告警,达到 85% 触发“提醒”级别告警。这样做的好处是,自动扩容只是兜底,真正的空间治理还是要基于主动告警提前做。

另外有几个容易踩的坑:

  • 包年包月和按量付费的计费方式不一样,自动扩容后费用会直接体现在账单里。如果客户用的是包年包月套餐,最好在页面里预估一下新增空间费用,或者搭配存储资源包来降低成本。
  • 如果实例已经因为空间满而被锁定为只读,自动扩容不一定来得及触发。这种时候必须先手动扩容或清理部分数据,解除锁定状态,再开启自动扩容作为后续保障。
  • 只读实例也要单独配置自动扩容,别以为主实例开了就万事大吉。多数客户挂了只读实例做读写分离,只读实例空间满了同样会影响读业务。

4. 第三招:清理与优化,根治空间黑洞

4.1 大表大字段先分流,少让数据库扛高成本

如果只靠扩容,存储空间永远在被动追着业务跑。真正解决问题要靠“节流”。我把第三招称为“清理与优化”,意思是从数据模型和 SQL 层面减少数据库对空间的消耗。

最直接的一项工作是大表治理。很多业务系统里的日志表、操作记录表、消息流水表,从上线第一天起就只增不减。DAS 表空间排行榜能帮我们精准抓到这些表,接下来要做的是分流:

  • 按时间做分区表:把日志表、流水表改成按月或按周分区,旧分区可以直接删除或归档,删除分区远比 DELETE 大量记录轻量。
  • 定期归档:超过一定时效的数据迁移到冷表、OSS 或数据仓库,线上只保留最近三个月或半年。归档任务可以用 DAS 或定时任务实现。
  • 大字段落地到对象存储:如果表里有图片、全文内容等 BLOB/TEXT 字段,建议把文件本身放到 OSS、本地文件系统,数据库只保存路径或引用。一个 10MB 的图片一旦进了数据库,同样的内容在备份、binlog、临时文件里都会被放大好几倍。

我遇到过最夸张的一个客户,一个product_intro字段是 TEXT 类型,里面存了几十万条商品 JSON 描述,光这一列就把单行数据撑到 20KB。后来全部迁到 OSS,数据库表空间直接缩到原来的三分之一。

4.2 SQL 洞察与索引优化,从源头减少空间膨胀

空间异常经常是 SQL 惹的祸,而不是数据本身。这也是为什么 DAS 的 SQL 洞察值得坚持用。它会把实例执行的 SQL 收集起来,通过性能分析找出消耗资源、临时文件、扫描行数特别多的语句。

举个例子:客户的一个统计报表 SQL 每天凌晨跑一次,查一个上亿行的订单表,但没有走索引,导致全表扫描。MySQL 为了执行里面的大排序,会把中间结果集写到磁盘临时表。这张临时表一口气吃了 20GB 空间,直接把实例磁盘打满。这种问题你手动清理空间是清不掉的,因为临时表在 SQL 执行期间占着磁盘,SQL 一结束空间又会慢慢释放。唯一有效的解决办法就是优化 SQL:加合适的索引,或者改写查询逻辑,让数据库不需要构造那么大的临时结果集。

DAS 的自动 SQL 优化功能会直接给出索引建议,甚至部分场景下可以在线创建索引。我给客户处理的时候一般都会去看一下 DAS 里的“慢 SQL”和“全表扫描”列表,发现这种高扫描行数的语句,优先让开发确认业务逻辑,然后由 DBA 在低峰期加索引。加完索引,磁盘空间告警经常不药而愈,比手动删数据干净得多。

4.3 手动清理空间的常用操作,有几个细节必须注意

除了 DAS 自动化的能力,有些场景还是需要我们手动清理空间。常见的操作包括调整 binlog 保留时长、清理大事务、释放表碎片。

binlog 清理可以通过设置binlog_expire_logs_seconds参数来缩短保留时间,比如从 7 天缩短到 2 天。但要注意:binlog 时长影响的是数据恢复和灾备能力,不是随便乱缩的,必须结合业务对数据安全的要求来定。对于大量更新场景,还可以定期 purge 旧的 binlog 文件。

表碎片清理是很多人做错的地方。有人以为执行DELETE FROM删除大量记录就能释放空间,实际上 InnoDB 删除数据只是把记录标记为删除,物理文件并不会立即缩小。正确做法是重建表:

-- 查看碎片情况 SELECT table_name, ROUND(data_length / 1024 / 1024, 2) AS data_mb, ROUND(index_length / 1024 / 1024, 2) AS index_mb, ROUND(data_free / 1024 / 1024, 2) AS free_mb FROM information_schema.tables WHERE table_schema = 'your_db' ORDER BY free_mb DESC; -- 整理碎片(业务低峰期执行) ALTER TABLE your_table ENGINE = InnoDB;

需要注意的是,ALTER TABLE ... ENGINE=InnoDB会复制表数据,期间会占用额外磁盘空间,对磁盘本来就不够的实例来说有风险。DBA 更推荐在线无锁变更工具,比如 gh-ost 或 pt-osc。如果实例开了 DAS 的自动空间扩展,也可以先用扩容把空间余量撑出来,再执行重建表操作,风险会更小。

4.4 临时文件与长事务的处理经验

临时文件导致的存储满,往往很隐蔽,因为“元凶”只是一条正在运行的 SQL。碰到空间分析里突然多出来的大文件,而且表空间排行一切正常,我通常会去看当前连接和执行中的 SQL:

SELECT id, db, user, state, command, time, info FROM information_schema.processlist WHERE command != 'Sleep' ORDER BY time DESC LIMIT 20;

如果发现一个长时间 RUNNING 的事务,或者一条Using temporary的慢 SQL,优先和开发确认能不能终止。杀掉异常 SQL 后,临时空间会立刻释放。长事务也会导致 undo log 膨胀,空间回收依赖事务结束,所以业务代码里一定要避免大事务跨多个业务操作长时间不提交。

5. 实战复盘:一次存储告警从发现到恢复的全过程

5.1 客户场景与告警信息

今年上半年有个做电商的客户,RDS MySQL 实例存储 100GB,某天早上 8 点半连续收到三条磁盘空间告警,空间使用率从 88% 跳到 95%,最后直接变成“实例锁定只读”。客户和我说,店铺订单不入库,用户下单直接失败,后台也登录不了。

面对这种情况,第一步不是慢慢分析,而是先恢复可用性。我在控制台手动将存储空间临时扩大到 150GB,等待实例状态恢复“运行中”,然后立刻开启 DAS 空间分析和存储自动扩容。注意,实例被锁定后不能只依赖自动扩容救场,必须先主动扩容解除锁定,再让自动扩容承担后续防御。

5.2 排查步骤与处理动作

实例恢复后,我按三招的顺序做排查:

先用 DAS 空间分析看趋势。图表显示空间在前一晚凌晨出现 20GB 的突增,表空间排行里order_detail和order_log两张表占了 45GB,其中order_log增长尤其明显。接着看 SQL 洞察,发现凌晨两点有个统计任务,对order_log执行了一次大范围更新,扫了全表,产生大量 binlog 和临时文件。

然后做清理与归档。order_log表接近 30GB,实际有效数据只有最近 7 天的订单日志需要实时查询。我跟客户确认后,写了一个归档任务:把 7 天前的数据迁移到阿里云 OSS,线上表保留最近 7 天。迁移后执行了一次在线重建表,物理空间降了 12GB。

最后处理慢 SQL。那个凌晨的统计任务,实际是没用上order_time的索引。我通过 DAS 自动 SQL 优化拿到了加索引的建议,在低峰期执行了:

ALTER TABLE order_log ADD INDEX idx_order_time (order_time);

执行完之后,这个统计任务只跑了 40 秒,以前要跑 25 分钟,而且没有再出现临时文件爆掉的情况。

5.3 处理前后指标对比与后续效果

处理完当天,实例空间使用率从 95% 降到 41%,可写状态恢复正常。一周后回访,空间使用率稳定在 45% 左右,此前那种“隔两天就要清一次”的情况没再出现。更重要的是,DAS 自动扩容已经把阈值设为 75%,就算某天大促突然来一波流量,存储也能自己先扩容扛住,不会再直接锁实例。

这个案例给我最大的触动是:手动清理可以救急,但只有把定位、扩容、优化三个环节串起来,才能让数据库空间问题从“反复发作”变成“偶尔关注一次”。

6. 常见问题与排查技巧实录

6.1 为什么 DAS 空间分析页没有数据?

新接入 DAS 的实例,通常要等采集任务跑完才能看到图表,这个等待期从几分钟到十几分钟不等。如果超过半小时还是空白,重点检查一下权限和版本:

  • 确认实例已经开通 DAS 服务,并且当前账号有查看实例的权限。
  • 确认实例类型在 DAS 支持范围内,比如 RDS MySQL、PolarDB MySQL 等;部分旧版本实例可能不支持全部空间分析功能。
  • 如果之前使用过免费版,后来没有开通专业版,部分分析功能可能受限,控制台一般会给出提示。

6.2 自动扩容后空间下降不明显,反而很快又满了?

自动扩容只是把存储容量变大,并不等于优化了空间结构。如果业务依然每天产生大量 binlog、临时文件,或者有大表持续膨胀,扩容只是延长了告警周期,没有解决根本问题。遇到这种情况,回到第一招和第三招:用空间分析找增长大头,用 SQL 洞察和归档清理降低写入量。

6.3 实例已经被锁成只读,自动扩容还能触发吗?

大概率不能。实例进入只读锁定后,控制台的一些自动变更动作会受限。正确流程是先手动扩容或通过清理空间把实例解锁,恢复“运行中”之后再用自动扩容做后续保障。别等到磁盘 100% 了才想起开自动扩容。

6.4 手动删除数据之后空间没减少,是不是没执行成功?

这通常不是没执行成功,而是 InnoDB 表碎片没有释放。DELETE只是把记录标记为删除,物理空间还留在数据文件里。你可以用data_free字段看看表碎片有多大,然后通过重建表或在线工具释放空间。重建表期间会额外占用空间,操作之前建议先看看实例还有没有足够余量。

下面这张速查表是我自己常用的排查路径,给读者做个参考:

问题现象优先排查项处理思路
空间持续匀速增长业务数据、binlog 保留时长做分区、归档,缩短 binlog 保留期
空间瞬时突增慢 SQL、临时表、大事务查 processlist,优化 SQL,终止异常会话
表空间排行里单表巨大线上大表缺少归档机制分区/归档/大字段迁 OSS
删除数据后空间不释放表碎片低峰期重建表或在线整理碎片
自动扩容后仍然告警触发阈值设得太高调低阈值、搭配 CPU/内存告警一起看

6.5 代理商在实际交付中的三点体会

第一,给客户出空间方案时不要只卖“扩容”。客户爱听扩容,因为简单直接,但真正的价值是把 DAS 的空间分析、SQL 优化都用起来,让客户以后少出事。第二,方案里一定要把费用讲清楚。自动扩容和 DAS 的部分高阶功能会产生额外费用,提前告诉客户,省得到月底对账单时解释半天。第三,定期帮客户巡检。哪怕客户自己开了自动扩容,我也会建议每季度看一次空间趋势,发现增长模型异常就早点治理。数据库空间不是一次搞定就永远没事的,它是一个持续演进的过程,DAS 这类工具的价值就是让我们在这个过程中少踩坑、少熬夜。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进