Я выполняю тысячи вычислений с помощью R и некоторого внешнего программного обеспечения. Чтобы отслеживать это, я построил конвейер в R в базе данных SQLite3. Чтобы все было сделано, я настроил его, чтобы позволить нескольким узлам нашего вычислительного кластера запускать 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
Я не могу понять, что происходит, и я до сих пор воспроизвести ошибку. Ошибка ясна, но я бы подумал, что моя рутина предотвратила это.
Любые мысли о том, почему это происходит?
Я бегу R под Linux, как видно:
> 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
Почему вы не просто использовать [ПРАГМА busy_timeout] (http://www.sqlite.org/pragma.html#pragma_busy_timeout)? –
Потому что я, видимо, не прочитал документацию полностью. :) Насколько я могу читать, это обходит мою рутину dbBeginTransaction? – MrGumble
Обновление: использование PRAGMA решило проблему, и я бросил свою функцию на кодовый свал. – MrGumble