【问题标题】:Is it possible to perform multiple DB operations in a single transaction in MongoDB?是否可以在 MongoDB 中的单个事务中执行多个 DB 操作?
【发布时间】:2015-07-16 06:32:29
【问题描述】:

假设我有两个集合 AB

我要执行一个操作

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

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

【问题讨论】:

    标签: mongodb transactions atomic


    【解决方案1】:

    是的,现在你可以了!

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

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

    【讨论】:

    • Arpit 如果您可以添加一个简单的 shell 示例,它将非常适合未来的读者。也许从官方文档本身复制。
    【解决方案2】:

    当涉及多个文档时,MongoDB 无法保证原子性。

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

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

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

    【讨论】:

    • 我无法合并集合。实际上我这样做是为了在 GridFS 中实现更新。因为没有办法直接更新 GridFS 中的文件。所以,我需要插入更新的文件并删除现有的文件。我想在一次交易中完成那部分
    • @dev 你为什么不这么说?这完全改变了你的问题。在 GridFS 中,您不是删除/删除单个文档,而是实际上是一堆文档(文件被分成块,每个块都是一个单独的文档)。同样使用 GridFS,您只对一个集合进行操作。但是在 GridFS 中有针对这种场景的特定解决方案。请将此作为一个新问题提出。
    • 我已经问了一个问题:stackoverflow.com/questions/29515327/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-14
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    相关资源
    最近更新 更多