
本文详解如何在 Go(基于 mgo 驱动)中正确创建 MongoDB 的 TTL 索引,重点说明 EnsureIndex 不会覆盖已有索引的限制,并提供可立即生效的完整实现方案。
本文详解如何在 go(基于 mgo 驱动)中正确创建 mongodb 的 ttl 索引,重点说明 `ensureindex` 不会覆盖已有索引的限制,并提供可立即生效的完整实现方案。
在 MongoDB 中,TTL(Time-To-Live)索引是一种特殊的单字段升序索引,配合 ExpireAfter 参数,可让数据库自动删除过期文档。但在使用 Go 的 mgo 驱动时,一个常见误区是:调用 EnsureIndex 并不能更新已存在的同名索引——它仅在索引不存在时创建,若索引已存在(即使结构不同),则直接跳过,导致 ExpireAfter 设置被静默忽略。
你提供的代码逻辑本身正确:
sessionTTL := mgo.Index{
Key: []string{"created"},
Background: true,
ExpireAfter: 5 * time.Second, // 注意:单位是秒(非纳秒/毫秒)
}
err := db.C("session").EnsureIndex(sessionTTL)
但问题根源在于:"created" 字段上已存在一个普通索引(例如之前仅用 []string{"created"} 创建过),而 EnsureIndex 不会重建或修改它。MongoDB 要求 TTL 行为必须通过带 expireAfterSeconds 选项的新索引启用,旧索引不具备该元数据,因此无法触发自动清理。
✅ 正确做法分两步:
-
显式删除旧索引(关键!)
使用 DropIndex 移除已存在的 "created" 相关索引(包括单字段或复合索引):// 删除名为 "created_1" 的索引(默认命名规则) if err := db.C("session").DropIndex("created_1"); err != nil { log.Printf("failed to drop index: %v", err) } // 或更安全地:删除所有以 "created" 开头的索引键(如需批量清理) -
重新创建带 TTL 的索引
确保 ExpireAfter 值为 time.Duration 类型,mgo 会自动将其转换为秒级整数(向下取整)。注意:MongoDB 要求该字段必须是 Date 或 ObjectId 类型,且文档中 "created" 必须是标准时间值(如 time.Now().UTC()):sessionTTL := mgo.Index{ Key: []string{"created"}, // 必须是升序(+1),不可为 "-1" Background: true, ExpireAfter: 5 * time.Second, // ✅ 有效:MongoDB 解析为 {"expireAfterSeconds": 5} } if err := db.C("session").EnsureIndex(sessionTTL); err != nil { panic(fmt.Sprintf("failed to create TTL index: %v", err)) }
? 验证是否生效:
连接 MongoDB Shell,执行:
db.session.getIndexes()
应看到类似条目:
{
"v": 1,
"key": { "created": 1 },
"name": "created_1",
"expireAfterSeconds": 5,
"background": true
}
其中 "expireAfterSeconds": 5 是 TTL 生效的关键标志。
⚠️ 注意事项:
- ExpireAfter 的最小有效值为 0(立即过期),但生产环境建议 ≥ 60 秒;低于 1 秒可能因后台任务扫描间隔导致延迟。
- TTL 删除由 MongoDB 后台线程每 60 秒执行一次,因此实际删除时间可能存在最多 60 秒延迟。
- "created" 字段必须存储为 UTC 时间(推荐 time.Now().UTC()),避免时区导致误删。
- mgo 已归档(不再维护),新项目建议迁移到官方驱动 go.mongodb.org/mongo-driver/mongo,其 TTL 创建语法更明确(options.Index().SetExpireAfterSeconds(5))。
总结:TTL 索引不是“设置即生效”,而是“创建即绑定”。EnsureIndex 的幂等性是一把双刃剑——它保障了部署安全性,但也要求开发者主动管理索引生命周期。务必在首次启用 TTL 或调整过期时间前,先清理旧索引,才能确保自动过期机制按预期工作。











