java.sql.SQLException: no se encontró un controlador adecuado al cargar DataFrame en Spark SQL

Me encuentro con un problema muy extraño al intentar cargar JDBC DataFrame en Spark SQL.

He probado varios clústeres de Spark: HILO, clúster independiente y modo pseudo distribuido en mi computadora portátil. Es reproducible en Spark 1.3.0 y 1.3.1. El problema ocurre en ambosspark-shell y al ejecutar el código conspark-submit. He probado los controladores MySQL y MS SQL JDBC sin éxito.

Considere la siguiente muestra:

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"
  ))
}

Hasta ahora todo bien, el esquema se resuelve correctamente:

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

Pero cuando evalúo DataFrame:

t1.take(1)

Se produce la siguiente excepción:

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)

Cuando intento abrir la conexión JDBC en el ejecutor:

import java.sql.DriverManager

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

funciona perfectamente

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

Cuando ejecuto el mismo código en Spark local, funciona perfectamente también:

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

Estoy usando Spark preconstruido con soporte Hadoop 2.4.

La forma más fácil de reproducir el problema es iniciar Spark en modo pseudo distribuido constart-all.sh script y ejecuta el siguiente comando:

/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

¿Hay alguna manera de solucionar esto? Parece un problema grave, por lo que es extraño que buscar en Google no ayude aquí.

Respuestas a la pregunta(4)

Su respuesta a la pregunta