qiniu / qmgo

Qmgo - The Go driver for MongoDB. It‘s based on official mongo-go-driver but easier to use like Mgo.
Apache License 2.0
1.3k stars 153 forks source link

关于多表事务 #235

Open fesed opened 2 years ago

fesed commented 2 years ago

我看案例中的事务是单表的,请问多表事务是该怎么实现

xsean2020 commented 2 years ago

事务不是基于 sessCtx实现的嘛, 保证操作多表使用同一个 sessCtx 就行了

LLiuHuan commented 2 years ago

事务不是基于 sessCtx实现的嘛, 保证操作多表使用同一个 sessCtx 就行了

大佬,有示例吗

orangesobeautiful commented 1 year ago

@fesed 使用 qmgo.Client 來進行操作即可 以下範例是 TestSession_AbortTransaction 函數的修改版

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/qiniu/qmgo"
    "go.mongodb.org/mongo-driver/bson"
)

const (
    // abortTransaction 是否要中斷 Transaction
    abortTransaction = false
)

func main() {
    bgCtx := context.Background()
    cfg := qmgo.Config{
        // 記得修改成自己的資料庫設定
        Uri: "mongodb://user:password@localhost:27017",
    }
    // 用 *qmgo.Client 才能達成多 Collection 操作需求
    qClient, err := qmgo.NewClient(bgCtx, &cfg)
    if err != nil {
        log.Fatalf("qmgo.Open failed, err=%s", err)
    }
    db := qClient.Database("testdb")
    col1 := db.Collection("coll1")
    col2 := db.Collection("coll2")
    sess, _ := qClient.Session()
    defer sess.EndSession(bgCtx)
    defer func() {
        _ = col1.DropCollection(bgCtx)
        _ = col2.DropCollection(bgCtx)
    }()

    // 定義 Transaction 中要做的事項
    // 注意 context 要使用的是傳進來的參數 sessCtx
    callback := func(sessCtx context.Context) (interface{}, error) {
        if _, err := col1.InsertOne(sessCtx, bson.M{"abc": int32(1)}); err != nil {
            return nil, err
        }
        if _, err := col2.InsertOne(sessCtx, bson.M{"xyz": int32(999)}); err != nil {
            return nil, err
        }
        if abortTransaction {
            _ = sess.AbortTransaction(sessCtx)
        }

        return nil, nil
    }

    // 執行 Transaction
    _, err = sess.StartTransaction(bgCtx, callback)
    if err != nil {
        log.Fatalf("StartTransaction failed, err=%s", err)
    }

    // 檢測資料有沒有寫入
    r := bson.M{}
    err = col1.Find(bgCtx, bson.M{"abc": 1}).One(&r)
    if err != nil {
        fmt.Println("abc found failed", err)
    } else {
        fmt.Println("find abc")
    }
    err = col2.Find(bgCtx, bson.M{"xyz": 999}).One(&r)
    if err != nil {
        fmt.Println("xyz found failed", err)
    } else {
        fmt.Println("find xyz")
    }
}