我一直在使用 Haskell 的 STM 库,我真的很喜欢编写事务的能力和 STM 的一般“你不能得到这个错误”的性质。
有充分的理由,STM 不允许事务中的 IO 操作。无法重试 IO 操作。(在此处插入发射导弹参考)。另一方面,数据库事务确实有一些非常相似的原子性保证。有没有一种可接受的方式将两者结合使用?
将不同类型的事务交织到一个事务概念中称为“事务提升”,目前在 Haskell 的 STM 中没有很好的方法来做到这一点。但是,有一种方法可以建立仅在提交或重试时执行的操作:http: //hackage.haskell.org/package/stm-io-hooks
此外,您可以尝试 twilight-stm 项目,它在事务结束和实际提交之间提供了一个明确的“暮光之城”。据我所知,提供的代码更多的是参考实现,而不是针对性能进行调整的代码,但是: http: //proglang.informatik.uni-freiburg.de/projects/twilight/
尽管如此,根据您的应用程序,它对于您的目的可能会非常快。
一些没有太多处理数据库的人的一般帮助:
您可以在技术上使用unsafeIOToSTM
,因此如果您通过修改数据库的 IO 操作保证原子性,那应该没问题。只需编写一个桥,unsafeIOToSTM
然后在您的代码中使用该桥,以避免在您的代码中添加不安全的东西。
您也可以使用 STM (IO a) 但这并不总是适合您的目的,例如
do r <- atomically $ do ...
r' <- r
或者
do r <- join . atomically $ do ...
从 STM 返回要执行的数据库查询的位置。这是安全的,但更受限制,因为您对 mVar 所做的操作不能从您返回的 IO 操作中修改(这在安全方面是一件好事,因为它保持了原子性)