在阅读了许多关于MongoDB事务的文档/文章后,我仍然需要进一步澄清.
Here上面写着:
MongoDB提供了两个使用事务的API.第一个是核心API,它的语法类似于关系数据库.第二个是回调API,它是在MongoDB中使用事务的recommended方法.
然而,它继续引入了核心API方法,完全没有触及推荐的方法.
官方文件here说,
此示例重点介绍了Transaction API的关键组件.特别是,它使用了回调API.回调接口:
- 启动一项交易
- 执行指定的操作
- 提交结果(或在出错时中止)
然而,当涉及到最重要的"执行指定的操作"步时,该示例没有显示任何相关代码.也就是说,正如在MongoDB Transactions In NodeJS,"still need a real example"中所要求的那样.
PS.如果示例被更改或消失,这里是Golang版本:
// WithTransactionExample is an example of using the Session.WithTransaction function.
func WithTransactionExample(ctx context.Context) error {
// For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
// uri := "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl"
// For a sharded cluster, connect to the mongos instances; e.g.
// uri := "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/"
uri := mtest.ClusterURI()
clientOpts := options.Client().ApplyURI(uri)
client, err := mongo.Connect(ctx, clientOpts)
if err != nil {
return err
}
defer func() { _ = client.Disconnect(ctx) }()
// Prereq: Create collections.
wcMajority := writeconcern.Majority()
wcMajority.WTimeout = 1 * time.Second
wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority)
fooColl := client.Database("mydb1").Collection("foo", wcMajorityCollectionOpts)
barColl := client.Database("mydb1").Collection("bar", wcMajorityCollectionOpts)
// Step 1: Define the callback that specifies the sequence of operations to perform inside the transaction.
callback := func(sessCtx mongo.SessionContext) (interface{}, error) {
// Important: You must pass sessCtx as the Context parameter to the operations for them to be executed in the
// transaction.
if _, err := fooColl.InsertOne(sessCtx, bson.D{{"abc", 1}}); err != nil {
return nil, err
}
if _, err := barColl.InsertOne(sessCtx, bson.D{{"xyz", 999}}); err != nil {
return nil, err
}
return nil, nil
}
// Step 2: Start a session and run the callback using WithTransaction.
session, err := client.StartSession()
if err != nil {
return err
}
defer session.EndSession(ctx)
result, err := session.WithTransaction(ctx, callback)
if err != nil {
return err
}
log.Printf("result: %v\n", result)
return nil
}
在我看来,从这个例子来看,最重要的"执行指定的操作"步是在回调中完成的.是真地吗?如果是这样的话,官方文件真的需要强调这一点.