与 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 交易的上下文的主要内容,如果未能解决你的问题,请参考以下文章

以太坊EVM源码分析学习记录

加工制造业经销商渠道管理系统:共享上下游信息,加速交易效率

“交易已中止”即使在故意中止时也会被抓住

高可用高扩展低延迟交易处理系统架构设计

如何将内存中的 MongoDB 与 Rails、Mongoid 和 Rspec 一起使用?

关于交易系统的一些设想