在MongoDB中是否可以在单个事务中执行多个数据库操作?

Is it possible to perform multiple DB operations in a single transaction in MongoDB?

假设我有两个集合 AB

我要进行手术

db.A.remove({_id:1});
db.B.insert({_id:"1","name":"dev"})

我知道 MongoDB 在文档级别保持原子性。是否可以在单个事务中执行上述一组操作?

MongoDB当涉及多个文档时不能保证原子性。

此外,MongoDB 不提供影响多个集合的任何单个操作。

当你想以原子方式做任何你真正想做的事情时,你需要将集合A和B合并为一个集合。请记住 MongoDB 是一个无模式数据库。您可以将不同类型的文档存储在一个集合中,并且可以执行单个原子更新操作,从而对文档执行多个更改。这意味着单个更新可以将 A 类型的文档转换为 B 类型的文档。

要区分同一集合中的不同类型,您可以有一个 type 字段并将其添加到您的所有查询中,或者您可以使用 duck-typing 并通过检查某个字段是否存在来识别类型$exists.

是的,现在可以了!

MongoDB长期在单个文档级别进行原子写操作。但是,MongoDB 直到 v4.0.0 才支持这种多文档操作的原子性。由于 MongoDB 事务的发布,多文档操作现在本质上是原子的。

但请记住,事务仅在使用 WiredTiger 存储引擎的副本集中受支持,在独立服务器中不受支持(但将来也可能在独立服务器上支持!)

这里有一个mongoshell的例子,官方文档也提供了:

// 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();

我建议您阅读this and this以更好地了解如何使用!