Недавно я столкнулся с подобной проблемой из-за того, что соединения MySQL были закрыты при превышении wait_timeout
экземпляра.Я наткнулся на ваше сообщение в RStudio Community и был вдохновлен вашим решением.Если вы все еще используете его и ищете решение, которое позволяет избежать лишнего запроса при переносе используемых вами фактических функций, вот пример, демонстрирующий то, что я придумал, вместе с примером, доказывающим, что он работает:
library(dplyr, warn.conflicts = FALSE)
library(pool)
library(RMariaDB)
generate_safe_query <- function(pool) {
function(db_function, ...) {
tryCatch({
db_function(pool, ...)
}, error = function(e) {
if (grepl("Lost connection to MySQL server during query", e$message)) {
# Preserve `validationInterval` so that it can be restored
validation_interval <- pool$validationInterval
# Trigger destruction of dead connection
pool$validationInterval <- 0
refreshed_connection <- poolCheckout(pool)
poolReturn(refreshed_connection)
# Restore original `validationInterval`
pool$validationInterval <- validation_interval
# Execute the query with the new connection
db_function(pool, ...)
} else {
# Unexpected error
stop(e)
}
})
}
}
mysql_pool <- dbPool(MariaDB(),
host = "127.0.0.1",
username = "root",
password = "",
dbname = "test")
safe_query <- generate_safe_query(mysql_pool)
# Works
safe_query(tbl, "notes")
#> # Source: table<notes> [?? x 2]
#> # Database: mysql 8.0.15 [root@127.0.0.1:/test]
#> id note
#> <int> <chr>
#> 1 1 NOTE1
# Set the `wait_timeout` to 5 seconds for this session
invisible(safe_query(dbExecute, "SET SESSION wait_timeout = 5"))
# Wait longer than `wait_timeout` to trigger a disconnect
Sys.sleep(6)
# Still works; warning will appear notifying that connection was
# destroyed and replaced with a new one
safe_query(tbl, "notes")
#> Warning: It wasn't possible to activate and/or validate the object. Trying
#> again with a new object.
#> # Source: table<notes> [?? x 2]
#> # Database: mysql 8.0.15 [root@127.0.0.1:/test]
#> id note
#> <int> <chr>
#> 1 1 NOTE1
safe_query(poolClose)
# Or, equivalently:
# poolClose(mysql_pool)
Создано в 2019-05-30 пакетом Представления (v0.3.0)
Функция, возвращаемая generate_safe_query
, будетработать с любой функцией запроса к базе данных (например, dbExecute
, dbGetQuery
и т. д.).Очевидно, что вы захотите обновить сообщение об ошибке, которое оно соответствует вашим потребностям.
Я также открыл свою собственную тему сообщества для опции, которая, по моему мнению, должна быть включена в dbPool
это уменьшило бы необходимость в таких обходных путях.