You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Shiny应用中使用future_promises调用SQLite内存数据库报错求助

问题原因与解决方案

你的问题核心在于SQLite内存数据库的进程隔离特性和数据库连接无法跨进程复用:

  • SQLite内存数据库(通过dbConnect(RSQLite::SQLite(), "")创建)仅存在于主进程的内存空间中,而multisession模式下future会在独立子进程运行,子进程无法访问主进程的内存数据。
  • 数据库连接对象是进程绑定的资源,不能直接传递给子进程复用。

修复步骤

  1. 替换内存数据库为磁盘存储的SQLite数据库,让主进程和子进程能通过磁盘文件共享数据。
  2. 在future代码块内部重新建立数据库连接,子进程必须自行创建连接才能访问数据库。
  3. 完成查询后关闭子进程的数据库连接,避免资源泄漏。

修复后的完整代码

library(shiny)
library(promises)
library(future)
library(DBI)
library(RSQLite)

plan(multisession)

# 改用磁盘存储的SQLite数据库,指定文件名
db_path <- "iris.db"
# 主进程初始化数据库并写入数据
db <- dbConnect(SQLite(), db_path, extended_types = TRUE)
dbWriteTable(db, "iris", iris)
dbDisconnect(db)  # 主进程完成写入后断开连接

nameUI <- function(id) {
  ns <- NS(id)
  tagList(
    selectInput(
      inputId = ns("rows"),
      label = "Number of rows",
      choices = c(10, 50, 100, 150),
      selected = 10
    ),
    actionButton(inputId = ns("start_job"),
                 label = "Start Job",
                 icon = icon("bolt")),
    tableOutput(ns("result_table"))
  )
}

nameServer <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      result_table <- reactiveVal(NULL)
      
      observeEvent(input$start_job, {
        print("start")
        rows <- as.numeric(input$rows)
        
        future_promise({
          Sys.sleep(5)
          # 子进程内部重新建立数据库连接
          child_db <- dbConnect(SQLite(), db_path, extended_types = TRUE)
          on.exit(dbDisconnect(child_db))  # 确保退出时自动关闭连接
          # 执行查询并返回结果
          dbGetQuery(child_db, sprintf("SELECT * FROM iris LIMIT %d", rows))
        }) %...>%
          result_table()
      })
      
      output$result_table <- renderTable({
        result_table()
      })
    }
  )
}

app <- function(){
  ui <- fluidPage(nameUI("app"))
  server <- function(input, output, session){
    nameServer("app")
  }
  shinyApp(ui, server)
}

app()

关键修改说明

  • 将内存数据库替换为磁盘文件iris.db,实现多进程数据共享。
  • 在future代码块内独立创建数据库连接,并通过on.exit确保查询完成后关闭连接,避免连接资源泄漏。
  • 使用dbGetQuery简化查询流程,替代dbSendQuery %>% dbFetch的链式调用,自动处理结果获取与语句清理。

内容的提问来源于stack exchange,提问作者MLEN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 19:07:26