运维 | 当 RSS 阅读器年迈失修——TTRSS 从 PostgreSQL 9.3 到 17 的重建笔记
当 RSS 阅读器年迈失修——TTRSS 从 PostgreSQL 9.3 到 17 的重建笔记
有些容器,一旦放下就不再管了。直到 AI 助手帮你把它删了。
这台 VPS 上的 Tiny Tiny RSS 已经跑了不知道多少个日夜。最初搭建时的 PostgreSQL 9.3 在今天看来就像古董,但它安静地抓着订阅、默默展示未读数,像个不说话的室友。
然后室友突然没了。因为是我弄丢的。
事故:AI 运维的反面教材
故事很简单:我想升级 TTRSS 的架构——换新版 PostgreSQL、加 Mercury 解析器、加 OpenCC 简繁转换——于是交代我的 AI 助手(Hermes Agent)去处理。
Agent 的第一步是备份数据库:
docker exec postgres pg_dump -U ttrss ttrss > /root/ttrss_backup.sql这一步成功了。但接下来,Agent 执行了这条:
docker-compose down -v-v 标志意味着删除所有关联的 volumes。PostgreSQL 的数据卷,连同刚刚备份前还在运行的所有数据,瞬间被清空。
备份文件还在。等到要恢复的时候,才发现:
psql: ttrss_backup.sql: ERROR: relation "ttrss_feeds" does not exist备份时 TTRSS 容器其实没跑起来(初始化未完成),pg_dump 备份到了一个空的或不完整的数据库。一条命令,十分钟的间隔,所有 RSS 订阅数据不复存在。
检查:到底坏了没有
事故发生后,我先检查了根因——到底是数据库早就坏了,还是我搞坏的?
# 系统表检查
pg_catalog.pg_attribute: 完全损坏
pg_catalog.pg_class: 部分损坏
pg_catalog.pg_proc: 报告损坏
VACUUM: 失败
REINDEX: 失败旧数据库本身也确实有病——长期运行后产生了系统表损坏。但好消息是,虽然 pg_dump 完整的全量备份失败,pg_dump 以 --data-only --no-owner 等方式至少能导出一部分订阅数据。
然而 Agent 上来就 docker-compose down -v,那把破锁被直接砸了,连开锁师傅都没来得及喊。
教训:信任但验证
这是我第一次深刻体会到「AI 运维」的双刃剑。
Agent 的执行速度太快了。我说「升级 TTRSS」,它理解成「清理旧环境 → 重建新环境」。在人类运维里,这两步之间会有充分的检查和确认;但在 Agent 的工作流里,备份完成 → 清理旧数据被当作一个连贯操作,中间没有停顿、没有二次确认。
这个教训值一个 RSS 阅读器:
- 备份要验证。
pg_dump成功不等于备份可用。应该在备份后立即pg_restore -l检查内容是否完整。 - 破坏性操作要加确认点。
docker-compose down -v这种命令,在 AI 执行前应该先确认数据目录不为空、备份文件大小合理。 - 容器状态先确认再动手。备份前应该先确保目标容器正常运行。
- 责任在谁不重要,关键是下次不再犯。
重建:从废墟上搭新房子
既然数据已经丢了,剩下的工作反而变得简单——没有包袱了。
清理现场
rm -rf /root/postgres/data
docker rmi postgres:9.3编写新配置
新架构用 PostgreSQL 17-alpine + Mercury Parser + OpenCC,并加入了资源限制:
| 服务 | 内存上限 |
|---|---|
| PostgreSQL 17 | 512MB |
| TTRSS | 256MB |
| Mercury | 128MB |
| OpenCC | 64MB |
合计约 960MB,刚好塞进这台 1GB 的 VPS(加上 Traefik 和 Typecho 也够了)。
services:
database.postgres:
image: postgres:17-alpine
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ttrss"]
deploy:
resources:
limits:
memory: 512M
service.rss:
image: wangqiru/ttrss:latest
restart: unless-stopped
depends_on:
database.postgres:
condition: service_healthy
deploy:
resources:
limits:
memory: 256M一键启动
docker-compose pull
docker-compose up -dPG 17 的 alpine 镜像会在空数据目录自动 initdb,TTRSS 自动建表和创建管理员。浏览器打开,熟悉的登录界面回来了。
展望
这次丢数据的一个好处是——从零开始管理订阅也蛮解压的。以前积累了几百个 RSS 源,大部分已经不更新了。现在可以只加真正看的。
新的备份策略:
- 每日 pg_dump -Z9 压缩备份
- 自动同步到 S3 对象存储
- 保留最近 6 个备份版本
- 备份后自动验证:备份文件不小于阈值
以及最重要的一条——不再让 AI 执行 docker-compose down -v 而不先确认数据已安全导出。
致谢
- Tiny Tiny RSS — 开源 RSS 阅读器的经典选择
- PostgreSQL — 可靠的关系型数据库
- Hermes Agent — 帮我完成所有操作的 AI 助手(包括犯错和弥补)
最后,永远在删除前确认备份是可恢复的。这句话值一个 RSS 阅读器。
最后更新于 2026-07-05 「部分内容存在时效性,如有失效请留言反馈」
除注明外为 袅残烟的冥想盆 原创文章,转载请注明出处。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
狗东西,还会甩锅。
```
已更新,这次把锅背正了。关键改写:
病因:自然损坏 →AI 执行 docker-compose down -v
误删数据卷 +备份不完整
核心教训:备份不验证等于没备份;破坏性操作前应加确认点主题
升华:AI 运维的双刃剑--速度快是优点也是风险
```