与 Mongoid 交易的上下文
Posted
技术标签:
【中文标题】与 Mongoid 交易的上下文【英文标题】:Context in transactions with Mongoid 【发布时间】:2021-09-06 17:47:48 【问题描述】:我需要使用mongoid的事务来执行一些操作,同时在失败的情况下保持一致性。
按照official documentation,我知道我必须在模型上启动会话并执行start_transaction
y commit_transaction
之间的操作。
我不明白的是,我必须在特定模型或模型实例上实例化会话。
我不明白是因为模型拥有执行该操作的助手(由于Monogid::Document
),或者我必须执行的操作必须与使用的模型/实例相关。
我的意思是,我应该能够执行此操作吗(我知道这或多或少是错误的,因为这些模型可能完全不相关):
ModelA.with_session do |s|
s.start_transaction
TotallyUnrelatedModelA.create!
TotallyUnrelatedModelB.create!
TotallyUnrelatedModelC.create!
s.commit_transaction
end
有人知道原因吗?
【问题讨论】:
【参考方案1】:Mongoid 目前不实现(或拥有)事务。这是一个驱动程序功能。
您不应该调用 commit_transaction
,因为这是驱动程序公开的事务 API 的第一次迭代,不支持自动重试。不幸的是,Mongoid 文档尚未更新以显示要使用的正确 API - 它是 here 所述的 with_transaction
方法。
要在驱动程序级别使用事务,启动事务的会话必须手动传递给每个操作,如 in the same doc 所示。
Mongoid 通过它所谓的持久性上下文没有这个要求。此功能在here 中有所描述,其要点是您可以覆盖在运行时读取或写入模型的位置,例如写入另一个集合。
会话是通过相同的运行时覆盖实现的。查看this page。 with_session
方法从活动持久性上下文中检索 client,然后确保 1) 在该客户端上存在活动会话,并且 2) 活动持久性上下文与该会话相关联,因此 3 ) 每个持久性操作(读取和写入)都会指定驱动程序的会话。
现在,回答你的问题:
我不明白的是,我必须在特定模型或模型实例上实例化会话。
Mongoid 需要知道在哪个客户端上启动会话。它可以从任何持久性上下文中获取该客户端。使用模型类或模型实例都没有关系。因为在 Mongoid 中一次只能激活一个会话(会话存储在当前线程的线程本地存储中),所以您必须仅使用与用于启动会话的同一客户端关联的模型,通过with_session
方法,无论 Mongoid 如何到达该客户端(通过模型类或模型实例)。
【讨论】:
感谢您的回复,但恐怕我不太明白。 Here (Mongoid documentation) 解释了如何使用 Mongoid 启动会话、执行事务和重试它们。以上是关于与 Mongoid 交易的上下文的主要内容,如果未能解决你的问题,请参考以下文章