RJDB C падает R, даже когда я пытаюсь поймать ошибку - PullRequest
0 голосов
/ 17 января 2020

Настройка:

У меня есть скрипт R на удаленном сервере, который должен подключаться к внешней базе данных, извлекать некоторые данные, запускать некоторые модели и сохранять результаты. Поскольку эта операция занимает много времени, я использую crontab, чтобы запланировать ее выполнение в ночное время (я пробовал разные начальные часы).

Чтобы подключиться к базе данных, я использую RJDB C (вы можете Предлагаю другой пакет, но мне бы очень хотелось не менять его :)). Двумя ключевыми функциями в рамках этого вопроса являются dbConnect (для создания соединения с внешней базой данных) и dbSendQuery (для отправки запросов).

Первоначальная проблема

Я понял, что по нескольким причинам иногда запросы, которые я отправляю в базу данных, отключаются на стороне базы данных (возможно, из-за некоторых проблем с обслуживанием). Не забывайте, что указанные запросы «правильные» - если я попытаюсь запустить их позже, они будут работать. Поскольку я не могу изменить поведение на стороне базы данных, я попытался реализовать некоторую устойчивость этого поведения в своем коде.

Первоначальное решение

Я написал ряд функций-оболочек для dBConnect и dBSendQuery, который должен в случае ошибки подождать некоторое время, а затем повторить попытку

jdbcDriver = JDBC(driverClass="oracle.jdbc.OracleDriver", 
                  classPath=here::here("OJDBC-Full/ojdbc6.jar"))
credentials = list()
credentials$user = 'user'
credentials$pass = 'password'
credentials$driver = jdbcDriver
credentials$host ="jdbc:oracle:thin:@//host" 
#I changed the user, pass, and host for privacy issues

dbConnectSafe = function(credentials) {
  connection = try(dbConnect(credentials$driver,
                             credentials$host,
                             credentials$user,
                             credentials$pass),
                   silent = T)
  timeout = 60
  while (class(connection) == "try-error") {
    print(paste("Problem with connection. Wait", timeout, "seconds and retry."))
    try(dbDisconnect(connection), silent = T)
    Sys.sleep(timeout)
    connection = try(dbConnect(credentials$driver,
                               credentials$host,
                               credentials$user,
                               credentials$pass),
                     silent = T)
    Sys.sleep(1)
    timeout = timeout + 60
  }
  return(connection)
}
dbSendQuerySafe = function(connection, query, credentials) {
  result = try(dbSendQuery(connection, query), silent = T)
  timeout = 60
  while (class(result) == "try-error") {
    print(paste("Poblem sending query. Waiting",timeout, 
                "seconds, then restart connection and retry."))
    Sys.sleep(timeout)
    try(dbDisconnect(connection), silent = T)
    connection <- dbConnectSafe(credentials)
    result = try(dbSendQuery(connection, query), silent = T)
    Sys.sleep(1)
    timeout = timeout + 60
  }
  return(result)
}

Помните, что фактические вызовы dbSendQuery находятся внутри функций, которые сами также находятся в try Catch. Что-то вроде:

someFunction = function(credentials){
    query = "select * from table"
    connection = dbConnectSafe(credentials)
    temp = dbSendQuerySafe(connection, query, credentials)
    data = data.table()
    go = T
    while(go){
        chunk = dbFetch(temp, 10000)
        if(nrow(chunk) > 0){
            data = rbind(data, data.table(chunk))
        }else{
            go = F
        }
    }
    dbClear(temp) 
    return(data)
}

done = tryCatch(someFunction( credentials),
                    error = function(err) {
                      print("Error")
                      return(F)

                    })

Актуальная проблема

Все это, чтобы прибыть сюда. Я понимаю, что иногда, в некоторой непредсказуемой форме, мой Rscript действительно падает. Учитывая приведенный выше пример кода, я ожидал, что после того, как мой запрос будет уничтожен на стороне БД, мой код будет обрабатывать его, ждать и повторять, не прерывая работу.

Однако я получаю следующее:

*** caught segfault ***
address (nil), cause 'unknown'

Traceback:
 1: .External(interface, as.character(obj), returnSig, method, ...)
 2: .jcall("java/sql/DriverManager", "Ljava/sql/Connection;", "getConnection",     as.character(url)[1], as.character(user)[1], as.character(password)[1],     check = FALSE)
 3: .local(drv, ...)
 4: dbConnect(credentials$driver, credentials$host, credentials$user,     credentials$pass)
 5: dbConnect(credentials$driver, credentials$host, credentials$user,     credentials$pass)
 6: doTryCatch(return(expr), name, parentenv, handler)
 7: tryCatchOne(expr, names, parentenv, handlers[[1L]])
 8: tryCatchList(expr, classes, parentenv, handlers)
 9: tryCatch(expr, error = function(e) {    call <- conditionCall(e)    if (!is.null(call)) {        if (identical(call[[1L]], quote(doTryCatch)))             call <- sys.call(-4L)        dcall <- deparse(call)[1L]        prefix <- paste("Error in", dcall, ": ")        LONG <- 75L        msg <- conditionMessage(e)        sm <- strsplit(msg, "\n")[[1L]]        w <- 14L + nchar(dcall, type = "w") + nchar(sm[1L], type = "w")        if (is.na(w))             w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L],                 type = "b")        if (w > LONG)             prefix <- paste0(prefix, "\n  ")    }    else prefix <- "Error : "    msg <- paste0(prefix, conditionMessage(e), "\n")    .Internal(seterrmessage(msg[1L]))    if (!silent && identical(getOption("show.error.messages"),         TRUE)) {        cat(msg, file = stderr())        .Internal(printDeferredWarnings())    }    invisible(structure(msg, class = "try-error", condition = e))})
10: try(dbConnect(credentials$driver, credentials$host, credentials$user,     credentials$pass), silent = T)
11: dbConnectSafe(credentials)
12: dbSendQuerySafe(connection, query, credentials)
13: doTryCatch(return(expr), name, parentenv, handler)
14: tryCatchOne(expr, names, parentenv, handlers[[1L]])
15: tryCatchList(expr, classes, parentenv, handlers)
16: tryCatch(someFunction(credentials = credentials),     error = function(err) {        print("Error")        return(F)    })
An irrecoverable exception occurred. R is aborting now ...

Почему R вылетает при использовании try-catch? Как я могу решить это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...