Deploy / build (push) Successful in 32s
- my-backup-was-using-someone-elses-api-quota (notes, 2026-10-15, pinned by its own evidence) - space-reclamation-wasnt-stuck-it-was-waiting (devops, 2026-10-14, pinned by its own samples) - adding-a-domain-to-someone-elses-mail-server (notes, 2025-05-06, backdated: no date/version pins) - embedding-fonts-so-a-pdf-looks-the-same-everywhere (engineering, 2025-01-22, backdated: no date/version pins) All four updatedDate 2026-10-16 so every lastmod stays honest; the two backdated posts carry no prose links (a backdated post may only link backwards). og measured rows=1/overflow=0, banners 8 rows/delta=2/overflow=0.
84 lines
5.6 KiB
Markdown
84 lines
5.6 KiB
Markdown
---
|
||
title: "空间回收没卡住,它只是在等明天早上 09:29"
|
||
description: "存储管理员那张卡整天写着 running,可用空间一动不动。其实 121 GiB 已经分两步回来了——然后下午又被写掉了 47 GiB。"
|
||
pubDate: 2026-10-14
|
||
updatedDate: 2026-10-16
|
||
category: devops
|
||
tags: ["synology", "btrfs", "snapshots", "storage", "nas"]
|
||
ogImage: /og/space-reclamation-wasnt-stuck-it-was-waiting.png
|
||
banner: /banners/space-reclamation-wasnt-stuck-it-was-waiting.png
|
||
draft: false
|
||
---
|
||
|
||
## 我问错了问题
|
||
|
||
我清掉几个文件夹,在 NAS 上点了空间回收,然后等。几个小时后,存储管理员那张卡还写着 **running**,可用空间看起来跟早上一样。我的问题是「它为什么什么都没回收」。
|
||
|
||
**它回收过了——两次**,而且其中一次比我删掉的东西大得多。测量回答的是另一个问题,而这才是这件事里最有意思的地方。
|
||
|
||
## 在相信任何东西之前,先给可用空间上定时采样
|
||
|
||
我没有去看那张进度卡,而是给 `volume1` 的可用空间做了当天每五分钟一次的采样:
|
||
|
||
| 时间 | 可用 | 事件 |
|
||
|---|---|---|
|
||
| 08:59 → 09:24 | 1134.1 GiB | 平——什么都没在回收 |
|
||
| **09:29** | **+69.0 GiB** | Class 快照 `…10.14-09.29.02` 轮转 |
|
||
| **09:34** | **+46.8 GiB** | Video 快照 `…10.14-09.30.35` 轮转 |
|
||
| **15:28:45** | — | DSM 日志:`Start to empty all recycle bins.` |
|
||
| **15:34** | **+5.0 GiB** | 清回收站结束——里面只有 5 GiB |
|
||
| 16:35 → 17:39 | **−39 GiB** | 新数据写入(一阵爆发) |
|
||
| 15:00 → 20:44 | **−47.2 GiB** | 净值:这个卷那天下午**丢**了空间 |
|
||
|
||
两次回收,合计约 121 GiB;然后 47 GiB 的新写入把下午吃掉了。「什么都没回来」是我这边的读法错误:我拿早上和晚上比,而晚上里面多了一整天的写入。
|
||
|
||
我特意手动清空的回收站是 **5 GiB**;我压根没想到的快照是 **115.8 GiB**。这个比例就是全部故事。
|
||
|
||
## 为什么那张卡写着 running,却什么都不代表
|
||
|
||
```text
|
||
$ synostgreclaim --get-all-status --verbose
|
||
{"state":"running","num_subvolume_remain":1,"now_runnable":true}
|
||
schedule_table: 168 × 1
|
||
run_time_option: run_all_time
|
||
```
|
||
|
||
`state: running` 加上 168 个 1 的调度表和 `run_all_time`,意思是这个任务被配置成**按设计 24×7 都处于 running**。它是调度状态,不是进度指示器——所以在某天完全无事可排的日子,这张卡照样这么写。而当时那台机器上**没有** `synostgreclaim` 进程、没有 btrfs balance、md2/dm-3 的 I/O 基本为零。那一刻没有任何东西在被回收,也没有任何东西卡住。
|
||
|
||
然后是日志,而 DSM 上它们大多是红鲱鱼:
|
||
|
||
- 回收任务本身什么都不记;
|
||
- `/var/log/space_operation.log` 是 LUKS 和卷列表的噪音;
|
||
- `/var/log/synorecycle.log` 是 `synounlinkd` 的路径噪音;
|
||
- 当天的 Log Center 里只有我自己那条清回收站的记录,外加几条 UPS 断电/来电的提示。
|
||
|
||
一个永远为真的 UI 状态字段,加上三个永远不会给出答案的日志文件:唯一剩下的仪器,就是**随时间变化的可用空间**。
|
||
|
||
## 没人告诉你的那个机制
|
||
|
||
空间回收释放的是**已删除的 btrfs 子卷**。它释放不了仍然被快照钉住的数据。那两个共享文件夹的保留策略是 **retention 1**(各留一代),所以**我删掉的任何东西,都要等到第二天的轮转、大约 09:29 / 09:30 才会变成可用空间**,一次跳几十 GB,然后安静 24 小时。
|
||
|
||
那两次跳变正是这个。它也就意味着,对于「我删了 50 GB 却什么都没发生」这个问题,在这台机器上的诚实答案是:「等明天早上再看」——而如果删掉的数据本来就在某个快照里面,答案是「等那个快照过期,之前不会释放」。
|
||
|
||
## 如果重来一次
|
||
|
||
1. **采样那个数字,不要采样状态。** 每五分钟量一次可用空间,比任何任务卡都更能回答「现在有没有事情在发生」,而且它同时让「回长」变得可见。
|
||
2. **读调度字段,不读状态字段。** `run_all_time` 解释了那个永久 running,而且不需要任何 bug 存在。
|
||
3. **搞清楚每个共享文件夹的保留策略。** 它是决定「删除何时变成可用空间」的那口钟;不知道它,每一次删除都会看起来坏掉一整天。
|
||
4. **把两本账分开。** 回收站(5 GiB)和快照(115.8 GiB)行为完全不同,也是两套心理模型。
|
||
5. **重新检查分母。** 这个卷平时就在以约 1.5 GiB/时 的速度被正常写入吃掉;回收回来 121 GiB、当天又花掉 47 GiB,只要你只比同一个数字的两个快照,这两件事看起来完全一样。
|
||
|
||
## 测量真正告诉我的,是这台机器的趋势
|
||
|
||
我本来是去修一个卡住的任务,结果带回来的是一条存储趋势:
|
||
|
||
```text
|
||
volume1 42 TB 已用 98% 剩 1.2 TB 近来约 -1.5 GiB/时(8 天 -344 GiB)
|
||
volume2 16 TB 已用 100% 剩 70 GB 约 -19 GiB / 2 天
|
||
健康 两个卷 btrfs corruption_errs 均为 0
|
||
所有 md 阵列 [UUUU] / [UU],没有在跑 balance
|
||
read/write_io_errs 与九月基线一致
|
||
```
|
||
|
||
所以有用的结论不是「回收是好的」。而是:**相对于写入速率,回收只是一个舍入误差**;在保留策略为 1 的前提下,删除并不是我以为的那根杠杆;而该拿来做告警的是趋势,不是那张任务卡。这跟[《你的磁盘快满告警在撒谎》](/posts/your-disk-full-alert-is-lying/)是同一课,只是从另一个方向来的:对**后果**告警(随时间变化的可用字节),因为机制自己的状态不是证据。
|