当前位置: 首页 > 工具软件 > Go-Mongo > 使用案例 >

go-zero mongo 创建事务

葛意远
2023-12-01

mongo-driver拥有两种创建事务的方式,但两种方式对事务的开启关闭提交回滚操作有所不同

1.useSession(此处用go-zero举例)

func (m *customUserModel) UseSession(ctx context.Context) error {
    db := m.conn.Database()
    col := db.Collection("demo")
    _, err := col.InsertOne(ctx, bson.M{"_id": "111", "name": "testSession"})
    if err != nil {
        return err
    }
    //第一个事务:成功执行
    err = db.Client().UseSession(ctx, func(sessionContext mongo.SessionContext) error {
        err = sessionContext.StartTransaction()
        if err != nil {
            fmt.Println(err)
            return err
        }

        //在事务内写一条id为“222”的记录
        _, err = col.InsertOne(sessionContext, bson.M{"_id": "111", "name": "testSession"})
        if err != nil {
            fmt.Println(err)
            return err
        }

        //在事务内写一条id为“333”的记录
        _, err = col.InsertOne(sessionContext, bson.M{"_id": "333", "name": "ddd"})
        if err != nil {
            err := sessionContext.AbortTransaction(sessionContext)
            if err != nil {
                return err
            }
            return err
        } else {
            err := sessionContext.CommitTransaction(sessionContext)
            if err != nil {
                return err
            }
        }
        return nil
    })
    if err != nil {
        return err
    }
    err = db.Client().UseSession(ctx, func(sessionContext mongo.SessionContext) error {
        err := sessionContext.StartTransaction()
        if err != nil {
            fmt.Println(err)
            return err
        }

        //在事务内写一条id为“222”的记录
        _, err = col.InsertOne(sessionContext, bson.M{"_id": "444", "name": "ddd"})
        if err != nil {
            fmt.Println(err)
            return err
        }

        //写重复id
        _, err = col.InsertOne(sessionContext, bson.M{"_id": "111", "name": "ddd"})
        if err != nil {
            abortErr := sessionContext.AbortTransaction(sessionContext)
            if abortErr != nil {
                return abortErr
            }
            return err
        } else {
            err := sessionContext.CommitTransaction(sessionContext)
            if err != nil {
                return err
            }
        }
        return nil
    })
    if err != nil {
        return err
    }
    return nil
}

2.StartSession

func (m *customUserModel) WithSession(ctx context.Context) error {
    db := m.conn.Database()
    col := db.Collection("demo")
    msgCol := db.Collection("message")
    _, err := col.InsertOne(ctx, bson.M{"_id": "111", "user_name": "testSession"})
    if err != nil {
        return err
    }
    session, err := db.Client().StartSession()
    if err != nil {
        return err
    }
    defer func() {
        session.EndSession(ctx)
    }()
    _, err = session.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
        if err != nil {
            return nil, err
        }
        _, err = col.InsertOne(sessCtx, bson.M{"_id": "222", "user_name": "testSession2"})
        if err != nil {
            return nil, err
        }
        _, err = col.InsertOne(sessCtx, bson.M{"_id": "333", "user_name": "testSession2"})
        if err != nil {
            return nil, err
        }
        //_, err = col.InsertOne(sessCtx, bson.M{"_id": "111", "user_name": "testSession"})
        //if err != nil {
        //    return nil, err
        //}
        return true, nil
    })
    if err != nil {
        return err
    }
    return nil
}

可以看出1方式需要手动管理事务的提交回滚,2方式则需要管理事务的开启与关闭。具体可点进UseSession和WithTransaction观察下源码即可

如果执行代码后提示:Transaction numbers are only allowed on a replica set member or mongos

可参考:

MongoDB 运行事务时报“Transaction numbers are only allowed on a replica set member or mongos“错误

参考:

golang操作mongodb的驱动mongo-go-driver的事务支持和访问控制

 类似资料: