mongodb atlas online archive适用于冷数据低频查询但需合规保留的场景,如审计追溯、法规存档;它自动将满足ttl条件的数据逻辑分离至云对象存储,保持统一查询入口,仅支持m10及以上付费集群,归档后数据只读且不可写入或修改。

在线归档(MongoDB Atlas Online Archive)适合什么场景
如果你用的是 MongoDB Atlas,且冷数据查询频率极低、但又不能丢弃(比如合规存档、审计追溯),Online Archive 是最省事的选择。它不是手动迁移,而是由 Atlas 自动把满足条件的文档从热集群“逻辑分离”到只读的云对象存储(如 AWS S3),同时保留统一查询入口。
关键限制必须提前确认:
-
Online Archive仅支持Atlas付费版(M10 及以上),免费共享集群不可用 - 归档后文档只能读,不能更新、删除或写入;聚合管道中
$lookup和事务不跨归档边界 - 查询时需显式启用归档层:在驱动中设置
readPreference=nearest并确保连接字符串含readConcern=majority - 归档策略靠 TTL 索引字段驱动,例如
archivedAt字段值 ≤ 当前时间即触发归档,不能按业务状态(如status: "completed")动态判断
手动分集合归档:aggregate + $out 的坑与绕法
当需要按业务逻辑(而非单纯时间)归档,或使用自建 MongoDB / 非 Atlas 环境时,aggregate 配合 $out 是主流做法。但它不是“复制+删除”,而是覆盖写入,容易误删目标集合已有数据。
安全执行要点:
- 永远先用
$merge替代$out:支持去重、保留原集合元数据,例如{ on: "_id", whenMatched: "replace", whenNotMatched: "insert" } - 归档前务必在源集合加
readConcern=majority,防止读到未提交的中间状态(尤其在分片集群中) - 不要一次性跑全量:
find加batchSize参数分批拉取,再逐批insertMany到归档集合,避免 OOM 或长事务阻塞 - 归档字段建议统一加
archived_at时间戳,而不是复用created_at—— 后者可能被业务逻辑修改,导致归档边界漂移
归档集合要不要建索引?看查询模式
很多人默认给归档集合建和主集合一样的索引,结果徒增写入开销和存储——归档集合几乎不写,但索引仍要维护。
真实决策依据:
- 如果归档后只做“按时间范围导出”(如查 2022 年全部订单),只需在
archived_at或原始date字段建单字段索引 - 如果常查某个业务维度(如
customer_id),且该字段在归档时未被投影剔除,就建对应索引;否则加字段成本远高于查询延迟 - 绝对不要在归档集合上建复合索引覆盖所有可能查询路径——归档数据是静态的,查询慢点可接受,但索引膨胀会持续吃磁盘
- 用
db.collection.getIndexes()定期检查,删掉半年没被explain("executionStats")命中的索引
为什么不能直接用 TTL 索引代替归档
TTL index 看似自动,但本质是“删”,不是“存”。它只适合临时缓存类数据(如 session、日志快照),不适合归档。
硬伤很明确:
- 删除不可逆:一旦过期,数据彻底丢失,无法回溯、无法合规审计
- 无迁移过程:不生成归档副本,不支持压缩/加密/异地备份等企业级要求
- 时间精度受限:TTL 最小单位是秒,无法按自然月/季度对齐归档周期
- 无法关联上下文:比如订单归档需同步归档其子文档(支付记录、物流轨迹),TTL 对嵌入式数组无效
真正要归档的历史数据,必须经过显式迁移动作,并留下操作日志、校验哈希、归档时间戳——这些是 TTL 根本不提供的能力。











