# MongoServerError: 命名空间 'mydb.mycoll' 的恢复令牌无效或已被修剪：resumeAfter 时间戳太旧

- **ID:** `mongodb/change-stream-resume-token-invalid-for-namespace`
- **领域:** mongodb
- **类别:** protocol_error
- **验证级别:** ai_generated
- **修复率:** 70%

## 根因

变更流的恢复令牌引用了已被修剪的操作日志条目，原因可能是操作日志大小限制，或变更流空闲时间超过操作日志窗口（Atlas 上通常为 24 小时）。

## 版本兼容性

| 版本 | 状态 | 引入 | 弃用 |
|------|------|------|------|
| MongoDB 5.0 | active | — | — |
| MongoDB 6.0 | active | — | — |
| MongoDB 7.0 | active | — | — |
| Atlas M10+ | active | — | — |

## 解决方案

1. ```
   从当前时间开始新的变更流，接受丢失事件的数据损失。在代码中：`collection.watch([], { resumeAfter: null, startAfter: null })` 或使用带有最近时间戳的 `startAtOperationTime`。
   ```
2. ```
   如果使用 Atlas，通过升级集群层级或启用长期操作日志保留（如果可用）来增加操作日志窗口。对于自管理，增加操作日志大小：`db.adminCommand({ replSetResizeOplog: 1, size: 102400 })`（以 MB 为单位）。
   ```
3. ```
   实现回退机制：将最后处理的文档 ID 存储在外部存储（例如 Redis）中，并使用 `startAfter` 与最后已知的 _id 来追赶，然后切换回恢复令牌。
   ```

## 无效尝试

- **** — The resume token is already invalid; a new change stream must be started from the current time, losing all events between the old token and now. (90% 失败率)
- **** — The oplog entry is permanently pruned; retrying will always fail. (100% 失败率)
- **** — The error is server-side; no driver can recover a pruned oplog entry. (95% 失败率)
