似乎关于并发访问的规则是未记录的(在Haskell方面)并且简单地假设开发人员熟悉正在使用的特定后端.对于生产需求而言,这是一个完全合理的假设,但对于随意的原型设计和开发,如果持久性*包更加自包含,那将会很好.
那么,管理对persistent-sqlite和family的并发访问的规则是什么?隐含地,如果我们有连接池,则必须允许某种程度的并发,但是通常创建单个连接池并且调用replicateM x $ forkIO (useThePool connectionPool)会产生以下错误.
user error (SQLite3 returned ErrorBusy while attempting to perform step.)
Run Code Online (Sandbox Code Playgroud)
编辑:现在下面是一些示例代码.
在下面的代码中,我分叉了6个线程(任意数字 - 我的实际应用程序执行3个线程).每个线程不断存储和查找记录(来自其他线程正在访问的记录的唯一记录,但这无关紧要),打印其中一个字段.
{-# LANGUAGE TemplateHaskell, QuasiQuotes
, TypeFamilies, FlexibleContexts, GADTs
, OverloadedStrings #-}
import Control.Concurrent (forkIO, threadDelay)
import Database.Persist
import Database.Persist.Sqlite hiding (get)
import Database.Persist.TH
import Control.Monad
import Control.Monad.IO.Class
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persist|
SomeData
myId Int
myData Double
MyId myId
|]
main = withSqlitePool "TEST" 40 $ \pool -> do
runSqlPool (runMigration migrateAll) pool
mapM_ forkIO [runSqlPool …Run Code Online (Sandbox Code Playgroud)