我正在使用R和一些外部软件执行数千次计算。 为了跟踪这一点,我在SQLite3数据库的R中构建了一个管道。 为了完成任务,我将其设置为允许计算集群上的多个节点运行R脚本。 当然,我们需要保持原子化,所以我正在积极开始交易。SQLite事务失败
为了避免崩溃的脚本试图让数据库锁的时候,我已经试图开始一个事务,如果失败,等待,然后将下面的代码重试:
dbBeginTransaction <- function(dbconn, state='DEFERRED', timeout=5, retries=10) {
state <- toupper(state)
if (!state %in% c('DEFERRED','IMMEDIATE','EXCLUSIVE')) stop('Attempt at illegal transaction.')
res <- NULL
exit <- FALSE
for (i in 1:retries) {
try(
res <- dbSendQuery(dbconn, paste('BEGIN',state,'TRANSACTION;'))
, silent=TRUE
)
# res is null if above query fails.
err <- dbGetException(dbconn)
if (err$errorNum == 0) { ## OK
#return(TRUE)
exit <- TRUE
break
} else if (err$errorNum == 5) { ## Database locked.
if (i == retries+1) {
cat('Database still locked after',i,'attempts.\n',file=stderr())
#return(FALSE)
exit <- FALSE
break
} else {
Sys.sleep(timeout)
}
} else {
## errorNum == 1 ## Already within transaction.
cat(err$errorMsg, '\n', file = stderr())
#return(FALSE)
exit <- FALSE
break
}
}
invisible(exit)
}
## Usage:
insert_results <- function(results) {
## Some preparing of results
if (dbBeginTransaction(conn, 'EXCLUSIVE') == FALSE) return(FALSE)
dbSendPreparedQuery(conn, 'INSERT INTO results (...) VALUES (...);', results)
dbCommit(conn)
}
## After a computation:
results <- magic()
if (!insert_results(results)) stop('Could not save results')
当调试,它的工作原理应该如此。但每一个现在,然后我得到这个奇怪的错误,并且脚本崩溃:
Error in sqliteSendQuery(conn, statement, bind.data) :
rsqlite_query_send: could not execute: database is locked
Calls: dbSendPreparedQuery ... dbSendPreparedQuery -> .local -> sqliteSendQuery -> .Call
Execution halted
我无法捉摸发生了什么,我还没有重现错误。 错误很明显,但我会认为我的例程阻止了它。
有关为什么会发生这种情况的任何想法?
我在linux下运行R,由所见:
> sessionInfo()
R version 3.1.2 (2014-10-31)
Platform: x86_64-unknown-linux-gnu (64-bit)
locale:
[1] LC_CTYPE=en_US LC_NUMERIC=C LC_TIME=en_US
[4] LC_COLLATE=en_US LC_MONETARY=en_US LC_MESSAGES=en_US
[7] LC_PAPER=en_US LC_NAME=C LC_ADDRESS=C
[10] LC_TELEPHONE=C LC_MEASUREMENT=en_US LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] RSQLite_1.0.0 DBI_0.3.1
为什么你不只是使用[PRAGMA busy_timeout]前添加dbBegin(CON) (http://www.sqlite.org/pragma.html#pragma_busy_timeout)? – 2014-11-04 08:09:32
因为我显然没有彻底阅读文档。 :)据我所知,这绕过了我的dbBeginTransaction例程? – MrGumble 2014-11-04 11:21:03
更新:使用PRAGMA解决了这个问题,我将代码转储功能投入使用。 – MrGumble 2015-01-15 14:24:56