【问题标题】:SQLITE_ERROR: Connection is closed when connecting from Spark via JDBC to SQLite databaseSQLITE_ERROR:从 Spark 通过 JDBC 连接到 SQLite 数据库时连接已关闭
【发布时间】:2015-09-30 07:16:42
【问题描述】:

我正在使用 Apache Spark 1.5.1 并尝试连接到名为 clinton.db 的本地 SQLite 数据库。从数据库表创建数据框工作正常,但是当我对创建的对象执行一些操作时,我收到下面的错误消息“SQL 错误或缺少数据库(连接已关闭)”。有趣的是,我仍然得到了操作的结果。知道我可以做些什么来解决问题,即避免错误吗?

spark-shell 的启动命令:

../spark/bin/spark-shell --master local[8] --jars ../libraries/sqlite-jdbc-3.8.11.1.jar --classpath ../libraries/sqlite-jdbc-3.8.11.1.jar

从数据库中读取:

val emails = sqlContext.read.format("jdbc").options(Map("url" -> "jdbc:sqlite:../data/clinton.sqlite", "dbtable" -> "Emails")).load()

简单计数(失败):

emails.count

错误:

15/09/30 09:06:39 WARN JDBCRDD: Exception closing statement java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (Connection is closed) at org.sqlite.core.DB.newSQLException(DB.java:890) at org.sqlite.core.CoreStatement.internalClose(CoreStatement.java:109) at org.sqlite.jdbc3.JDBC3Statement.close(JDBC3Statement.java:35) at org.apache.spark.sql.execution.datasources.jdbc.JDBCRDD$$anon$1.org$apache$spark$sql$execution$datasources$jdbc$JDBCRDD$$anon$$close(JDBCRDD.scala:454) at org.apache.spark.sql.execution.datasources.jdbc.JDBCRDD$$anon$1$$anonfun$8.apply(JDBCRDD.scala:358) at org.apache.spark.sql.execution.datasources.jdbc.JDBCRDD$$anon$1$$anonfun$8.apply(JDBCRDD.scala:358) at org.apache.spark.TaskContextImpl$$anon$1.onTaskCompletion(TaskContextImpl.scala:60) at org.apache.spark.TaskContextImpl$$anonfun$markTaskCompleted$1.apply(TaskContextImpl.scala:79) at org.apache.spark.TaskContextImpl$$anonfun$markTaskCompleted$1.apply(TaskContextImpl.scala:77) at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59) at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47) at org.apache.spark.TaskContextImpl.markTaskCompleted(TaskContextImpl.scala:77) at org.apache.spark.scheduler.Task.run(Task.scala:90) at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:214) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) res1: Long = 7945

【问题讨论】:

  • 看起来您提供给 .sqlite 数据库文件的路径存在问题。您是否尝试过使用绝对路径?或者至少不以'..'开头?也许您正在运行的进程没有父目录的权限。
  • @aguibert:我刚刚尝试了数据库的绝对路径,但问题仍然出现。我还将 clinton.sqlite 的权限更改为 777,但这也无济于事。 Spark 1.4.1 和新发布的 1.5.1 也出现此问题。

标签: sqlite jdbc apache-spark apache-spark-sql


【解决方案1】:

我得到了同样的错误today,重要的一行就在异常之前:

15/11/30 12:13:02 INFO jdbc.JDBCRDD: 关闭连接

15/11/30 12:13:02 WARN jdbc.JDBCRDD: 异常关闭语句 java.sql.SQLException: [SQLITE_ERROR] SQL 错误或缺少数据库(连接已关闭) 在 org.sqlite.core.DB.newSQLException(DB.java:890) 在 org.sqlite.core.CoreStatement.internalClose(CoreStatement.java:109) 在 org.sqlite.jdbc3.JDBC3Statement.close(JDBC3Statement.java:35) 在 org.apache.spark.sql.execution.datasources.jdbc.JDBCRDD$$anon$1.org$apache$spark$sql$execution$datasources$jdbc$JDBCRDD$$anon$$close(JDBCRDD.scala:454)

所以Spark成功关闭了JDBC连接,然后又关闭了JDBC语句


查看源代码,close() 被调用两次

第 358 行(org.apache.spark.sql.execution.datasources.jdbc.JDBCRDD,Spark 1.5.1)

context.addTaskCompletionListener{ context => close() }

第 469 行

override def hasNext: Boolean = {
  if (!finished) {
    if (!gotNext) {
      nextValue = getNext()
      if (finished) {
        close()
      }
      gotNext = true
    }
  }
  !finished
}

如果您查看 close() 方法(第 443 行)

def close() {
  if (closed) return

您可以看到它检查了变量 closed,但该值从未设置为 true。

如果我没看错的话,这个 bug 还在 master 中。我已经提交了bug report

【讨论】:

  • 感谢您的回复并提交错误报告!
  • 好吧,我什至已经修好了 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
  • 2017-01-24
  • 1970-01-01
相关资源
最近更新 更多