使用GoLang进行MongoDB事务的示例

13

我需要一个用GoLang实现MongoDB事务的示例。

我正在使用这个MongoDB的golang驱动程序:

https://github.com/mongodb/mongo-go-driver

目前还没有清晰的文档说明如何实现事务。

有人可以帮帮我吗?

2个回答

28

这可能会让人感到困惑。以下是一个简单的例子。

if session, err = client.StartSession(); err != nil {
    t.Fatal(err)
}
if err = session.StartTransaction(); err != nil {
    t.Fatal(err)
}
if err = mongo.WithSession(ctx, session, func(sc mongo.SessionContext) error {
    if result, err = collection.UpdateOne(sc, bson.M{"_id": id}, update); err != nil {
        t.Fatal(err)
    }
    if result.MatchedCount != 1 || result.ModifiedCount != 1 {
        t.Fatal("replace failed, expected 1 but got", result.MatchedCount)
    }

    if err = session.CommitTransaction(sc); err != nil {
        t.Fatal(err)
    }
    return nil
}); err != nil {
    t.Fatal(err)
}
session.EndSession(ctx)
你可以查看完整的示例

这对我帮助很大。同时感谢教程。 - Sreenath
有关于旧的问题(关于事务),但是是针对批量写入的:https://stackoverflow.com/questions/53621036/bulkwrite-does-not-support-multi-document-transaction-by-using-mongo-go-driver - Wan B.
会话和事务有什么区别? - Cirelli94
2
@Cirelli94 https://docs.mongodb.com/manual/core/transactions/#transactions-and-sessions - Muhammad Tariq

12

这将有所帮助

ctx := context.Background()
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
    panic(err)
}

db := client.Database("testdb")
defer db.Client().Disconnect(ctx)
col := db.Collection("testcol")

// transaction
err = db.Client().UseSession(ctx, func(sessionContext mongo.SessionContext) error {
    err := sessionContext.StartTransaction()
    if err != nil {
        return err
    }

    _, err = col.InsertOne(sessionContext, bson.M{"_id": "1", "name": "berry"})
    if err != nil {
        return err
    }

    _, err = col.InsertOne(sessionContext, bson.M{"_id": "2", "name": "gucci"})
    if err != nil {
        sessionContext.AbortTransaction(sessionContext)
        return err
    }
    if err = session.CommitTransaction(sessionContext); err != nil {
        return err
    }
    return nil
})

1
为什么只有第二个操作失败时才中止事务,为什么不在第一个操作抛出错误时也中止事务呢?@berryberry - Aayush Taneja
我同意你的观点 @AayushTaneja,但是这样我们每次与数据库交互时都必须使用 if else 语句吗?还是只需要在最后一行使用 CommitTransaction?我认为我们只需要在最后一行使用 CommitTransaction。请纠正我。 - Muhammad Tariq
这绝对是最干净的解决方案 - 太棒了 :-). Mongo开发人员添加了一些帮助文档,改变了您的解决方案。在此处查看示例块 - sessionContext.AbortTransaction(sessionContext) 应该是 sessionContext.AbortTransaction(context.Background()) 确保即使传递给会话的上下文正在关闭或会话调用期间发生超时,中止也能完成。session.CommitTransaction(sessionContext) -> sessionContext.CommitTransaction(context.Background()) - TopherGopher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接