提问人:schmijos 提问时间:8/17/2023 更新时间:8/17/2023 访问量:45
转义 ActiveRecord 事务
Escape an ActiveRecord transaction
问:
如何转义 ActiveRecord 事务?请考虑以下代码:
Model1.transaction do
response = http.request(request)
OutboundRequestLog.create(request:, response:)
# … do stuff with Model1
raise ActiveRecord::Rollback
end
OutboundRequestLog
是一个 ActiveRecord 模型,应独立于事务进行持久化。上面的代码也会导致回滚。Model1
OutboundRequestLog
是否有可能以某种方式从当前事务中排除查询? 我已经尝试了以下方法:
- 获取新的数据库连接 这里的缺点是水豚似乎不能很好地应对。我不确定问题是事务性固定装置还是执行器线程。
Thread.new do ActiveRecord::Base.connection_pool.with_connection do OutboundRequestLog.create(request:, response:) end end.value
- 通过 ActiveJob#perform_later 延迟日志记录并不容易,因为 net/http 请求不容易序列化,并且序列化的有效负载可能很大。
答:
2赞
smathy
8/17/2023
#1
顺便说一句,将需要很长时间(就数据库世界而言需要很长时间,即超过~几十毫秒)的东西放入数据库事务中通常不是一个好主意,例如。HTTP 请求。您应该在进入事务之前执行此操作(因此,在您的用例中,您可以在进入事务之前登录),然后打开事务以仅执行与数据库相关的操作。
其他选项是使用子句配置模型以使用不同的数据库连接(在此处查看更多信息),或者您可以手动检出
连接,只需知道您需要重新检入即可。我会将这种复杂性隐藏在方法中。OutboundRequestLog
connects_to
OutboundRequestLog
虽然它主要用于副本和分片,但我通常会使用这种方法。它更整洁,手动更少(老实说,如果我登录到数据库,我总是会认为最终我会想要一个专用的数据库,这样我就不会影响我的用户体验)connects_to
评论
0赞
schmijos
8/17/2023
很酷的想法使用.我读了起来。它应该开箱即用,因为它似乎不是故意的 您能否进一步详细说明为什么数据库事务不应该花费很长时间?如果我不锁定并且范围很窄,我看不出有什么问题。connects_to
Rails uses the model class name for the connection specification name
It's important to connect to your database in a single model and then inherit from that model for the tables rather than connect multiple individual models to the same database.
0赞
smathy
8/18/2023
是的,因为事务打开的时间越长,提交时序列化失败的可能性就越大。
评论