我正在使用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