使用 unsafeIOToSTM 从数据库中读取是否安全?
Safe to use unsafeIOToSTM to read from database?
在这个伪代码块中:
atomically $ do
if valueInLocalStorage key
then readValueFromLocalStorage key
else do
value <- unsafeIOToSTM $ fetchValueFromDatabase key
writeValueToLocalStorage key value
使用unsafeIOToSTM
安全吗?文档说:
STM实现往往会运行多次交易,所以如果你的IO有任何副作用,你需要做好准备。
基本上,如果事务失败是因为其他线程wroteValueToLocalStorage
,当重试事务时它将return存储的值而不是再次从数据库中获取。
STM 实现将中止已知无效且需要重新启动的事务。这可能发生在 unsafeIOToSTM 的中间,因此请确保您没有获取任何需要释放的资源(异常处理程序在中止事务时被忽略)。例如,这包括使用句柄执行任何 IO。弄错这个可能会导致随机死锁。
这是我最担心的。从逻辑上讲,如果 fetchValueFromDatabase
不打开新连接(即使用现有连接),一切都应该没问题。还有其他我遗漏的陷阱吗?
当 IO 运行s 时,事务可能看到了不一致的内存视图。由于事务的实现方式,您期望在整个程序中为真的不变量在事务中可能并不为真。通常这对程序员来说是不可见的,但是使用 unsafeIOToSTM 可以暴露它。
key
是单个值,没有可打破的不变量。
我建议从 STM 交易中 I/O 只是一个坏主意。
大概你想要的是避免两个线程同时进行数据库查找。我会做的是:
查看该项目是否已在缓存中。如果是,我们就完成了。
如果不是,用"I'm fetching this"标志标记它,提交STM事务,从数据库中获取它,然后做第二个STM事务将它插入到缓存(并删除标志)。
如果该项目已被标记,retry
交易。这会阻塞调用线程,直到第一个线程从数据库中插入值。
在这个伪代码块中:
atomically $ do
if valueInLocalStorage key
then readValueFromLocalStorage key
else do
value <- unsafeIOToSTM $ fetchValueFromDatabase key
writeValueToLocalStorage key value
使用unsafeIOToSTM
安全吗?文档说:
STM实现往往会运行多次交易,所以如果你的IO有任何副作用,你需要做好准备。
基本上,如果事务失败是因为其他线程
wroteValueToLocalStorage
,当重试事务时它将return存储的值而不是再次从数据库中获取。STM 实现将中止已知无效且需要重新启动的事务。这可能发生在 unsafeIOToSTM 的中间,因此请确保您没有获取任何需要释放的资源(异常处理程序在中止事务时被忽略)。例如,这包括使用句柄执行任何 IO。弄错这个可能会导致随机死锁。
这是我最担心的。从逻辑上讲,如果
fetchValueFromDatabase
不打开新连接(即使用现有连接),一切都应该没问题。还有其他我遗漏的陷阱吗?当 IO 运行s 时,事务可能看到了不一致的内存视图。由于事务的实现方式,您期望在整个程序中为真的不变量在事务中可能并不为真。通常这对程序员来说是不可见的,但是使用 unsafeIOToSTM 可以暴露它。
key
是单个值,没有可打破的不变量。
我建议从 STM 交易中 I/O 只是一个坏主意。
大概你想要的是避免两个线程同时进行数据库查找。我会做的是:
查看该项目是否已在缓存中。如果是,我们就完成了。
如果不是,用"I'm fetching this"标志标记它,提交STM事务,从数据库中获取它,然后做第二个STM事务将它插入到缓存(并删除标志)。
如果该项目已被标记,
retry
交易。这会阻塞调用线程,直到第一个线程从数据库中插入值。