对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
Docs 菜单

事务

在本指南中,您可以了解如何使用 Ruby 驱动程序执行事务。事务允许您执行一系列操作,这些操作仅在整个事务提交后才会更改数据。如果事务中的任何操作不成功,驱动程序就会停止事务,并在所有数据更改变得可见之前予以丢弃。这种功能称为原子性

在MongoDB中,事务在逻辑会话中运行。会话是要按顺序运行的一组相关读取或写入操作。 会话可为一群组操作启用因果一致性,并允许您在符合ACID的ACID 事务中运行操作,该ACID 事务满足原子性、一致性、隔离性和持久性的预期。MongoDBACID 一致性保证ACID 事务操作中涉及的数据保持一致,即使操作遇到意外错误。

使用Ruby驱动程序时,您可以通过在客户端上调用 start_session 方法来启动会话。然后,您可以在会话中执行事务。

警告

仅在创建会话的 Mongo::Client 上运行的操作中使用会话。使用具有不同 Mongo::Client 的会话会导致操作错误。

MongoDB在某些客户端会话中实现因果一致性。因果一致性模型ACID 一致性保证在分布式系统中,会话中的操作按因果顺序运行。客户端观察到的结果与因果关系或操作之间的依赖关系一致。示例,如果您执行一系列操作,其中一个操作在逻辑上依赖于另一个操作的结果,则任何后续读取都会反映这种依赖关系。

为了保证因果一致性,客户端端会话必须满足以下要求:

  • 启动会话时,驱动程序必须启用因果一致性选项。该选项默认启用。

  • 操作必须在单个线程的单个会话中运行。否则,会话或线程必须相互传达optime和集群时间值。 要查看传达这些值的两个会话的示例,请参阅MongoDB Server手册中的因果一致性示例

  • 您必须使用 :majority读关注(read concern)。

  • 您必须使用 :majority写关注(write concern)。这是默认的写关注(write concern)值。

下表描述了因果一致会话提供的ACID 一致性保证:

保证
说明

读取写入操作

读取操作会反映之前写入操作的结果。

单调读取

读取操作不会返回反映比先前读取操作更早的数据状态的结果。

单调写入

如果写入操作必须先于其他写入操作,则服务器会先运行此写入操作。

示例,如果调用 insert_one() 插入文档,然后调用 update_one() 修改插入的文档,则服务器首先运行插入操作。

读取后写入

如果写入操作必须在其他读取操作之后执行,服务器会先执行读取操作。

示例,如果您调用 find() 来检索文档,然后调用 delete_one() 来删除检索到的文档,则服务器会先运行查找操作。

提示

要学习;了解有关本节中提到的概念的更多信息,请参阅以下MongoDB Server手册条目:

调用 start_session 方法启动会话后,您可以使用 Mongo::Session 类中的方法来管理会话状态。下表描述了可用于管理ACID 事务的方法:

方法
说明

start_transaction

在此会话上启动新ACID 事务。如果会话中已运行活动ACID 事务,则无法启动ACID 事务。您可以通过传递

作为参数来设立ACID 事务选项,包括读关注(read concern)、写关注(write concern)和读取偏好(readHash preference)。

commit_transaction

提交此会话的活动事务。如果此会话没有活动事务、事务已经结束或存在写冲突(write conflict),则此方法返回错误。

abort_transaction

结束此会话的活动事务。 如果该会话没有活动事务或者事务已提交或结束,则此方法将返回错误。

with_transaction

在调用提供的区块之前启动ACID 事务,并在区块完成时提交ACID 事务。如果区块中的任何操作或提交操作导致暂时性ACID 事务错误,则将再次执行区块和/或提交。

此示例定义了一个 run_transaction 方法,用于修改 sample_mflix数据库集合中的数据。 该代码执行以下操作:

  • 创建 Mongo::Collection 实例以访问权限moviesusers 集合。

  • 指定ACID 事务的读关注和写入关注。

  • 启动ACID 事务。

  • 将文档插入 movies集合并打印结果。

  • 更新 users集合中的文档并打印结果。

database = client.use('sample_mflix')
movies_collection = database[:movies]
users_collection = database[:users]
def run_transaction(session, movies_collection, users_collection)
transaction_options = {
read_concern: { level: "snapshot" },
write_concern: { w: "majority" }
}
session.with_transaction(transaction_options) do
# Inserts document into the "movies" collection
insert_result = movies_collection.insert_one({ name: 'The Menu', runtime: 107 }, session: session)
puts "Insert completed: #{insert_result.inspect}"
# Updates document in the "users" collection
update_result = users_collection.update_one({ name: 'Amy Phillips'}, { "$set" => { name: 'Amy Ryan' }}, session: session)
puts "Update completed: #{update_result.inspect}"
end
end
# Starts a session
session = client.start_session
begin
# Runs the transaction
run_transaction(session, movies_collection, users_collection)
puts "Transaction committed successfully."
rescue Mongo::Error::OperationFailure => e
puts "Transaction failed and was aborted. Error: #{e.message}"
ensure
session.end_session
end

注意

不支持并行操作

Ruby驱动程序不支持在单个事务中运行并行操作。

如果您使用的是MongoDB Server v8.0 或更高版本,则可以使用 bulk_write 方法在单个ACID 事务中对多个命名空间执行写入操作。有关更多信息,请参阅批量写入操作指南。

要学习;了解有关本指南中提到的概念的更多信息,请参阅MongoDB Server手册中的以下页面:

要学习;了解有关ACID compliance的更多信息,请参阅MongoDB网站上的《数据库管理系统中ACID属性指南》一文。

要了解有关插入操作的更多信息,请参阅插入文档指南。

要进一步了解本指南所提及的方法和类型,请参阅以下 API 文档: