【发布时间】:2015-07-16 06:32:29
【问题描述】:
假设我有两个集合 A 和 B
我要执行一个操作
db.A.remove({_id:1});
db.B.insert({_id:"1","name":"dev"})
我知道 MongoDB 在文档级别保持原子性。是否可以在单个事务中执行上述一组操作?
【问题讨论】:
标签: mongodb transactions atomic
假设我有两个集合 A 和 B
我要执行一个操作
db.A.remove({_id:1});
db.B.insert({_id:"1","name":"dev"})
我知道 MongoDB 在文档级别保持原子性。是否可以在单个事务中执行上述一组操作?
【问题讨论】:
标签: mongodb transactions atomic
是的,现在你可以了!
MongoDB 长期以来一直在单个文档级别进行原子写入操作。但是,直到v4.0.0,MongoDB 才在多文档操作的情况下支持这种原子性。由于 MongoDB Transactions 的发布,多文档操作现在本质上是原子操作。
但请记住,事务仅在使用 WiredTiger 存储引擎的副本集中受支持,而在独立服务器中不支持(但将来也可能在独立服务器上支持!)
这是官方文档中也提供的 mongo shell 示例:
// Start a session.
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
employeesCollection = session.getDatabase("hr").employees;
eventsCollection = session.getDatabase("reporting").events;
// Start a transaction
session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );
//As many operations as you want inside this transaction
try {
employeesCollection.updateOne( { employee: 3 }, { $set: { status: "Inactive" } } );
eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } );
} catch (error) {
// Abort transaction on error
session.abortTransaction();
throw error;
}
// Commit the transaction using write concern set at transaction start
session.commitTransaction();
session.endSession();
【讨论】:
当涉及多个文档时,MongoDB 无法保证原子性。
另外,MongoDB 不提供任何影响多个集合的单一操作。
当您想以原子方式执行您真正想做的任何事情时,您需要将集合 A 和 B 合并到一个集合中。请记住,MongoDB 是一个无模式数据库。您可以将不同类型的文档存储在一个集合中,并且可以执行单个原子更新操作,从而对文档执行多项更改。这意味着一次更新可以将 A 类型的文档转换为 B 类型的文档。
要区分同一集合中的不同类型,您可以有一个 type 字段并将其添加到所有查询中,或者您可以使用鸭子类型并通过检查某个字段是否为 $exists 来识别类型。
【讨论】: