通过设置 TTL 使集合中的数据过期
本文档介绍了 MongoDB 的“生存时间”或TTL收集功能。TTL 集合可以将数据存储在 MongoDB 中,并mongod在指定的秒数或特定的时钟时间后自动删除数据。
数据过期对于某些类别的信息很有用,包括机器生成的事件数据、日志和仅需要保留一段有限时间的会话信息。
特殊的TTL 索引属性支持 TTL 集合的实现。TTL 功能依赖于后台线程,mongod该线程读取索引中的日期类型值并从集合中删除过期文档。
要创建 TTL 索引,请使用createIndex(). 指定索引字段,该索引字段可以是日期类型,也可以是包含日期类型值的数组。使用该expireAfterSeconds选项指定 TTL 值(以秒为单位)。
笔记:
TTL索引是单字段索引。复合索引不支持 TTL 属性。有关 TTL 索引的更多信息,请参阅 TTL 索引。
您可以expireAfterSeconds使用该命令修改现有 TTL 索引collMod。
指定秒数后使文档过期
要在自索引字段经过指定秒数后使数据过期,请在保存 BSON 日期类型值或 BSON 日期类型对象数组的字段上创建 TTL 索引,并在字段中指定正expireAfterSeconds非零值。expireAfterSeconds 当自其索引字段中指定的时间起经过该字段中的 秒数时,文档将过期。[ 1 ]
TTL 索引expireAfterSeconds值必须在0且 2147483647包含在内。
log_events例如,以下操作在集合的字段上创建索引 createdAt,并指定 expireAfterSeconds的值,10将过期时间设置为 指定的时间后十秒createdAt。
db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 10 } )
将文档添加到log_events集合时,将 createdAt字段设置为当前时间:
db.log_events.insertOne( {
"createdAt": new Date(),
"logEvent": 2,
"logMessage": "Success!"
} )
log_events 当文档的createdAt值 [ 1 ]早于指定的秒数时,MongoDB将自动从集合中删除文档expireAfterSeconds。
| [ 1 ] | ( 1 , 2 ) 如果字段包含一组 BSON 日期类型对象,则如果至少一个 BSON 日期类型对象早于 中指定的秒数,则数据将过期 expireAfterSeconds。 |
|---|---|
文档在特定时钟时间过期
要在特定时钟时间使文档过期,请首先在保存 BSON 日期类型值或 BSON 日期类型对象数组的字段上创建 TTL 索引,并指定expireAfterSeconds值0。对于集合中的每个文档,将索引日期字段设置为与文档到期时间相对应的值。如果索引日期字段包含过去的日期,MongoDB 会认为该文档已过期。
log_events例如,以下操作在集合的字段上创建索引 expireAt并指定 expireAfterSeconds的值0:
db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )
对于每个文档,设置 的值expireAt以对应于文档应过期的时间。例如,以下 insertOne()操作添加一个到期时间为 的文档July 22, 2013 14:00:00。
db.log_events.insertOne( {
"expireAt": new Date('July 22, 2013 14:00:00'),
"logEvent": 2,
"logMessage": "Success!"
} )
log_events 当文档的expireAt值早于 中指定的秒数expireAfterSeconds(在本例中即早几秒)时,MongoDB 将自动从集合中删除文档0 。因此,数据在指定 expireAt值处过期。
使用 NaN 配置的索引
警告
可能的数据丢失
当 TTL 索引
expireAfterSeconds设置为 时NaN,升级、降级和某些同步操作可能会导致意外行为并可能导致数据丢失
不要在 TTL 索引配置中设置expireAfterSeconds为。NaN
在 MongoDB 5.0 之前,当 TTL 索引设置为 时expireAfterSeconds, NaNMongoDB 会记录错误并且不会删除任何记录。
从 MongoDB 5.0.0 - 5.0.13(和 6.0.0 - 6.0.1),NaN被视为 0. 如果 TTL 索引配置为expireAfterSeconds设置为 NaN,则所有 TTL 索引的文档都会立即过期。
从 MongoDB 5.0.14(和 6.0.2)开始,服务器将不再使用expireAfterSeconds设置为 的TTL 索引NaN。
但是,仍有一些情况可能会导致意外行为。文件可能会过期:
- 在从 MongoDB 5.0.0 - 5.0.13(或 6.0.0 - 6.0.1)初始同步到早期版本期间。
- 从早期版本升级到 MongoDB 5.0.0 - 5.0.13 时。
- 从 5.0 之前的版本恢复集合时
mongodump到 MongoDB 5.0.0 - 5.0.13(或 6.0.0 - 6.0.1)实例。
为了避免出现问题,请删除或更正任何配置错误的 TTL 索引。
识别配置错误的索引
在中运行以下脚本
mongosh壳。该脚本在旧 shell 中不起作用mongo。function getNaNIndexes() { const nan_index = []; const dbs = db.adminCommand({ listDatabases: 1 }).databases; dbs.forEach((d) => { const listCollCursor = db .getSiblingDB(d.name) .runCommand({ listCollections: 1 }).cursor; const collDetails = { db: listCollCursor.ns.split(".$cmd")[0], colls: listCollCursor.firstBatch.map((c) => c.name), }; collDetails.colls.forEach((c) => db .getSiblingDB(collDetails.db) .getCollection(c) .getIndexes() .forEach((entry) => { if (Object.is(entry.expireAfterSeconds, NaN)) { nan_index.push({ ns: `${collDetails.db}.${c}`, index: entry }); } }) ); }); return nan_index; }; getNaNIndexes();纠正错误配置的索引
使用该
collMod命令更新expireAfterSeconds脚本发现的任何配置错误的值。作为替代方案,您可以
drop使用命令来重新创建任何配置错误的 TTL 索引createIndexes。