RMySQL dbDisconnect 没有关闭数据库连接
Posted
技术标签:
【中文标题】RMySQL dbDisconnect 没有关闭数据库连接【英文标题】:RMySQL dbDisconnect is not closing the DB connection 【发布时间】:2021-05-04 00:46:27 【问题描述】:Rmysql 库的 dbDisconnect 函数没有正确关闭数据库连接。这是我在本地测试过的代码
library(RMySQL)
execute.query <- function(query)
mydb_con <- dbConnect(MySQL(), user='username', password='pass', dbname='student', host='db_ip')
returned_data <- dbGetQuery(mydb_con, query)
dbDisconnect(mydb_con)
return(returned_data)
for(i in c(1:100))
print(paste0("i = ", i));
execute.query(paste("select now()"));
顺序执行 100 个 SQL 查询,理想情况下应该为每个查询创建和关闭新的数据库连接,但在执行上述代码后,我可以看到使用此命令 watch netstat -nat | grep db_ip |wc -l
数据库连接数从 0 变为 20,直到第一次20 个查询,将其保持在 18-24 个连接,直到第 100 个查询,10 秒后程序完成执行,耗尽到 0 个连接。
所以我的问题是为什么 dbDisconnect 没有关闭数据库连接?这里有什么我想了解的细微差别吗?
由于这个问题,当连接数达到 1000+ 时,我的生产 R 代码(巨大的多线程遗留代码库)中出现 Failed to connect to database: Error: Can't create TCP/IP socket (24)
错误
【问题讨论】:
【参考方案1】:理想情况下,在多线程环境中,您应该将 dbConnect 保持在静态块中,并在单独的方法中执行查询,然后 dbdisconnect atlast 相当于 java 中的 finally 块。当您收到连接异常时,您应该尝试重新连接。如果您在多线程环境中为每个查询打开一个新连接,那么您肯定会同时打开许多文件并且您会收到此错误。
【讨论】:
我同意理想情况下我应该在静态块中创建连接并重新使用它,但正如我所说,这是一个遗留代码库,我有点不愿意改变这个逻辑。如果 dbDisconnect 工作正常,那么即使在多线程环境中,它一次也不会超过 100 个连接 ***.com/questions/33098894/…。这很好地解释了您的参考如何在多线程环境中更新,以及 on.exit 的重要性,它保证了数据库连接关闭。【参考方案2】:我更喜欢dbSendQuery()
函数,理想情况下来自odbc
包,正如前面的答案所述,只需保持连接打开,然后发送后续查询即可。
如果要确保连接有效,则可以使用dbIsValid
,如果无效,请重新连接。这应该使查询执行非常安全。
警告,代码可能无法直接运行。
library(odbc)
mydb_con <- dbConnect(MySQL(), user='username', password='pass', dbname='student', host='db_ip')
execute.query <- function(query)
result <- odbc::dbSendQuery(mydb_con, query)
returned_data <- odbc::dbFetch(result)
odbc::dbClearResult(result)
return(returned_data)
【讨论】:
感谢您的回答。如果我找不到 DB 连接泄漏的原因,我会尝试这种方法 btw 为什么你更喜欢 odbc 而不是 RMySQL 包? 我认为它比 DBI 更快,维护得更好,但不能给你任何具体的事实。我还大量使用dbplyr
包中的build_sql
,这对于构建带有R 插入的SQL 命令非常有用。以上是关于RMySQL dbDisconnect 没有关闭数据库连接的主要内容,如果未能解决你的问题,请参考以下文章
在 SUSE Tumbleweed 上安装 RMySQL 的新错误