Java.sql.SQLException: При загрузке DataFrame в Spark SQL не найдено подходящего драйвера

Я поражаю очень странную проблему при попытке загрузить JDBC DataFrame в Spark SQL.

Я пробовал несколько Spark-кластеров - YARN, автономный кластер и псевдораспределенный режим на моем ноутбуке. Он воспроизводится как на Spark 1.3.0, так и на 1.3.1. Проблема возникает как в spark-shell, так и при выполнении кода с spark-submit. Я пробовал драйверы MySQL и MS SQL JDBC без успеха.

Рассмотрим следующий пример:

val driver = "com.mysql.jdbc.Driver"
val url = "jdbc:mysql://localhost:3306/test"

val t1 = {
  sqlContext.load("jdbc", Map(
    "url" -> url,
    "driver" -> driver,
    "dbtable" -> "t1",
    "partitionColumn" -> "id",
    "lowerBound" -> "0",
    "upperBound" -> "100",
    "numPartitions" -> "50"
  ))
}

Пока все хорошо, схема правильно решена:

t1: org.apache.spark.sql.DataFrame = [id: int, name: string]

Но когда я оцениваю DataFrame:

t1.take(1)

Выполняется следующее исключение:

15/04/29 01:56:44 WARN TaskSetManager: Lost task 0.0 in stage 0.0 (TID 0, 192.168.1.42): java.sql.SQLException: No suitable driver found for jdbc:mysql://<hostname>:3306/test
    at java.sql.DriverManager.getConnection(DriverManager.java:689)
    at java.sql.DriverManager.getConnection(DriverManager.java:270)
    at org.apache.spark.sql.jdbc.JDBCRDD$$anonfun$getConnector$1.apply(JDBCRDD.scala:158)
    at org.apache.spark.sql.jdbc.JDBCRDD$$anonfun$getConnector$1.apply(JDBCRDD.scala:150)
    at org.apache.spark.sql.jdbc.JDBCRDD$$anon$1.<init>(JDBCRDD.scala:317)
    at org.apache.spark.sql.jdbc.JDBCRDD.compute(JDBCRDD.scala:309)
    at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:277)
    at org.apache.spark.rdd.RDD.iterator(RDD.scala:244)
    at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:35)
    at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:277)
    at org.apache.spark.rdd.RDD.iterator(RDD.scala:244)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:61)
    at org.apache.spark.scheduler.Task.run(Task.scala:64)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:203)
    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)

Когда я пытаюсь открыть соединение JDBC с исполнителем:

import java.sql.DriverManager

sc.parallelize(0 until 2, 2).map { i =>
  Class.forName(driver)
  val conn = DriverManager.getConnection(url)
  conn.close()
  i
}.collect()

он отлично работает:

res1: Array[Int] = Array(0, 1)

Когда я запускаю тот же код на локальном Spark, он отлично работает:

scala> t1.take(1)
...
res0: Array[org.apache.spark.sql.Row] = Array([1,one])

Я использую Spark, предварительно созданный с поддержкой Hadoop 2.4.

Самый простой способ воспроизвести проблему - запустить Spark в псевдораспределенном режиме с помощью start-all.sh script и выполнить следующую команду:

/path/to/spark-shell --master spark://<hostname>:7077 --jars /path/to/mysql-connector-java-5.1.35.jar --driver-class-path /path/to/mysql-connector-java-5.1.35.jar

Есть ли способ справиться с этим? Это похоже на серьезную проблему, поэтому странно, что поиск в googling здесь не помогает.

Ответ 1

По-видимому, недавно была опубликована эта проблема:

https://issues.apache.org/jira/browse/SPARK-6913

Проблема заключается в java.sql.DriverManager, который не видит драйверы, загруженные ClassLoaders, кроме bootstrap ClassLoader.

В качестве временного обходного пути можно добавить необходимые драйверы для загрузки classpath исполнителей.

UPDATE: этот запрос на разрыв устраняет проблему: https://github.com/apache/spark/pull/5782

ОБНОВЛЕНИЕ 2: Исправление, объединенное с Spark 1.4

Ответ 2

Для записи данных в MySQL

In spark 1.4.0, вы должны загружать MySQL перед записью в него, потому что он загружает драйверы в функции загрузки, но не на функцию записи. Мы должны поставить jar на каждого рабочего node и установить путь в файле spark-defaults.conf на каждом node. Эта проблема была исправлена ​​в искровом свете 1.5.0

https://issues.apache.org/jira/browse/SPARK-10036

Ответ 3

Мы застряли на Spark 1.3 (Cloudera 5.4), и поэтому я нашел этот вопрос, и Wildfire ответил, потому что это позволило мне перестать ударить головой о стену.

Думаю, я поделился бы тем, как мы получили драйвер в путь к загрузке: мы просто скопировали его в /opt/cloudera/parcels/CDH -5.4.0-1.cdh5.4.0.p0.27/lib/hive/lib на всех узлах.

Ответ 4

Я использую spark-1.6.1 с SQL-сервером, все еще сталкиваюсь с той же проблемой. Мне пришлось добавить библиотеку (sqljdbc-4.0.jar) в lib в экземпляре и ниже строки в файле conf/spark-dfault.conf.

spark.driver.extraClassPath lib/sqljdbc-4.0.jar