与 Mongoid 交易的上下文
Context in transactions with Mongoid
我需要使用 mongoid 的事务来执行一些操作,同时在发生故障时保持一致性。
在 official documentation 之后,我了解到我必须在模型上启动会话并在 start_transaction
和 commit_transaction
之间执行操作。
我不明白的是我必须在特定模型或模型实例上实例化会话。
我不知道是不是因为模型有一个助手来执行该操作(由于 beign Monogid::Document
)或者我必须执行的操作必须与 model/instance 有关使用过。
我的意思是,我是否可以执行此操作(我知道这或多或少是错误的,因为这些模型可能完全不相关):
ModelA.with_session do |s|
s.start_transaction
TotallyUnrelatedModelA.create!
TotallyUnrelatedModelB.create!
TotallyUnrelatedModelC.create!
s.commit_transaction
end
有人知道原因吗?
Mongoid 目前不执行(或没有)事务。这是驱动程序的功能。
您不应该调用 commit_transaction
,因为这是驱动程序公开的事务 API 的第一次迭代,并且不支持自动重试。不幸的是,Mongoid 文档尚未更新以显示正确的 API 用法 - 它是 here.
中描述的 with_transaction
方法
要在驱动程序级别使用事务,启动事务的会话必须手动传递给每个操作,如 in the same doc 所示。
Mongoid 通过所谓的持久性上下文 没有该要求。这个功能有点描述 here,它的要点是你可以覆盖在运行时读取或写入模型的位置,例如写入另一个集合。
会话是通过相同的运行时覆盖实现的。回顾this page。 with_session
方法从活动持久性上下文中检索 client,然后确保 1) 在该客户端上有一个活动的会话,以及 2) 活动持久性上下文与之相关联会话,以便 3) 每个持久性操作(读取和写入)都将向驱动程序指定该会话。
现在,回答你的问题:
The thing I do not understand is the fact that I have to instantiate a session on a specific model or instance of a model.
Mongoid 需要知道在哪个客户端上启动会话。它可以从任何持久性上下文中获取该客户端。使用模型 class 还是模型实例并不重要。因为在 Mongoid 中一次只能有一个会话处于活动状态(会话存储在当前线程的线程本地存储中),您必须仅使用与用于启动会话的同一客户端相关联的模型,通过with_session
方法,无论 Mongoid 如何到达客户端(通过模型 class 或模型实例)。
我需要使用 mongoid 的事务来执行一些操作,同时在发生故障时保持一致性。
在 official documentation 之后,我了解到我必须在模型上启动会话并在 start_transaction
和 commit_transaction
之间执行操作。
我不明白的是我必须在特定模型或模型实例上实例化会话。
我不知道是不是因为模型有一个助手来执行该操作(由于 beign Monogid::Document
)或者我必须执行的操作必须与 model/instance 有关使用过。
我的意思是,我是否可以执行此操作(我知道这或多或少是错误的,因为这些模型可能完全不相关):
ModelA.with_session do |s|
s.start_transaction
TotallyUnrelatedModelA.create!
TotallyUnrelatedModelB.create!
TotallyUnrelatedModelC.create!
s.commit_transaction
end
有人知道原因吗?
Mongoid 目前不执行(或没有)事务。这是驱动程序的功能。
您不应该调用 commit_transaction
,因为这是驱动程序公开的事务 API 的第一次迭代,并且不支持自动重试。不幸的是,Mongoid 文档尚未更新以显示正确的 API 用法 - 它是 here.
with_transaction
方法
要在驱动程序级别使用事务,启动事务的会话必须手动传递给每个操作,如 in the same doc 所示。
Mongoid 通过所谓的持久性上下文 没有该要求。这个功能有点描述 here,它的要点是你可以覆盖在运行时读取或写入模型的位置,例如写入另一个集合。
会话是通过相同的运行时覆盖实现的。回顾this page。 with_session
方法从活动持久性上下文中检索 client,然后确保 1) 在该客户端上有一个活动的会话,以及 2) 活动持久性上下文与之相关联会话,以便 3) 每个持久性操作(读取和写入)都将向驱动程序指定该会话。
现在,回答你的问题:
The thing I do not understand is the fact that I have to instantiate a session on a specific model or instance of a model.
Mongoid 需要知道在哪个客户端上启动会话。它可以从任何持久性上下文中获取该客户端。使用模型 class 还是模型实例并不重要。因为在 Mongoid 中一次只能有一个会话处于活动状态(会话存储在当前线程的线程本地存储中),您必须仅使用与用于启动会话的同一客户端相关联的模型,通过with_session
方法,无论 Mongoid 如何到达客户端(通过模型 class 或模型实例)。