事务
Overview
在本指南中,您可以学习如何使用 MongoDB Go Driver 执行事务。 事务允许您运行一系列操作,这些操作在提交事务之前不会更改任何数据。如果事务中的任何操作返回错误,驱动程序就会取消事务,并在所有数据更改变得可见之前予以丢弃。
在 MongoDB 中,事务在逻辑会话中运行。会话是一组要按顺序运行的相关读取或写入操作。会话可以实现一组操作的因果一致性,或支持在 ACID 事务中执行操作。MongoDB 保证事务操作中涉及的数据保持一致,即使操作遇到意外错误。
使用 Go 驱动程序时,您可以从 Client
实例创建一个新会话,并将其类型定义为 Session
。我们建议您将客户端重复用于多个会话和事务,而不是每次都实例化新客户端。
警告
仅应将 Session
与创建它的 Client
(或关联的 Database
或 Collection
)一起使用。将 Session
与其他 Client
一起使用会导致操作错误。
警告
Session
多个 goroutine 并发使用 的实现并不安全。
会话方法
在客户端上使用 StartSession()
方法启动会话后,可以使用返回的 Session
提供的设立集修改会话状态。下表描述了这些方法:
方法 | 说明 |
---|---|
| Starts a new transaction, configured with the given options, on
this session. Returns an error if there is already
a transaction in progress for the session. To learn more about
this method, see the startTransaction() page in the Server manual. Parameter: TransactionOptions Return Type: error |
| Ends the active transaction for this session. Returns an
error if there is no active transaction for the session or the
transaction has been committed or ended. To learn more about
this method, see the abortTransaction() page in the Server manual. Parameter: Context Return Type: error |
| Commits the active transaction for this session. Returns an
error if there is no active transaction for the session or if the
transaction was ended. To learn more about
this method, see the commitTransaction() page in the Server manual. The CommitTransaction() method is an idempotent function, which
means that you can attempt to commit a transaction multiple times without changing data after the first successful commit.
A transaction can succeed but return an error with the
UnknownTransactionCommitResult label. If you rerun the
CommitTransaction() method after receiving this error,
your data is not changed by the repeat attempts.Parameter: Context Return Type: error |
| Starts a transaction on this session and runs the fn
callback.Parameters: Context , fn func(ctx SessionContext) , TransactionOptions Return Type: interface{} , error |
| Ends any existing transactions and closes the session. Parameter: Context Return Type: none |
Session
还提供检索会话属性和修改可变会话属性的方法。 查看API文档以学习;了解有关这些方法的更多信息。
会话和事务选项
您可以在会话级别和ACID 事务级别设立选项,以自定义驾驶员执行ACID 事务的方式。以下步骤描述了如何为给定 Session
内运行的所有事务设立选项:
创建一个
TransactionOptions
实例。您可以为给定会话中运行的所有事务指定写关注(write concern)、读关注(read concern)和读取偏好(read preference)等选项。调用
SetDefaultTransactionOptions()
方法,并将TransactionOptions
实例作为参数传递,从而创建SessionOptions
实例。您还可以指定其他会话选项,例如在
SessionOptions
实例中指定因果一致性。将
SessionOptions
实例传递给client.StartSession()
方法。
以下代码指定会话和ACID 事务选项,然后使用这些选项创建会话:
txnOpts := options.Transaction().SetReadConcern(readconcern.Majority()) sessOpts := options.Session().SetDefaultTransactionOptions(txnOpts) session, err := client.StartSession(sessOpts) if err != nil { return err }
注意
不支持并行操作
Go驾驶员不支持在单个ACID 事务中运行并行操作。
例子
以下示例显示如何通过以下步骤创建会话、创建事务以及提交多文档插入操作:
使用
StartSession()
方法从客户端创建会话。使用
WithTransaction()
方法启动事务。插入多个文档。
WithTransaction()
方法执行插入并提交事务。如果任何操作导致错误,WithTransaction()
将处理取消事务。使用
EndSession()
方法关闭 ACID 事务和会话。
wc := writeconcern.Majority() txnOptions := options.Transaction().SetWriteConcern(wc) // Starts a session on the client session, err := client.StartSession() if err != nil { panic(err) } // Defers ending the session after the transaction is committed or ended defer session.EndSession(context.TODO()) // Inserts multiple documents into a collection within a transaction, // then commits or ends the transaction result, err := session.WithTransaction(context.TODO(), func(ctx context.Context) (interface{}, error) { result, err := coll.InsertMany(ctx, []interface{}{ bson.D{{"title", "The Bluest Eye"}, {"author", "Toni Morrison"}}, bson.D{{"title", "Sula"}, {"author", "Toni Morrison"}}, bson.D{{"title", "Song of Solomon"}, {"author", "Toni Morrison"}}, }) return result, err }, txnOptions)
如果您需要对事务拥有更多控制,您可以在完整代码示例中找出一个说明如何手动创建、提交和结束事务的示例
更多信息
有关插入操作的更多信息,请参阅 插入文档基础知识页面。
有关在 Go 驱动程序中指定写关注的更多信息,请参阅写关注。
有关在 Go 驱动程序中使用会话和事务的更多示例,请参阅关于多文档 ACID 事务的开发者博客文章。
API 文档
要进一步了解本指南所讨论的任何类型或方法,请参阅以下 API 文档: