2015-04-28 12 views
10

Mam bardzo dziwny problem przy próbie załadowania JDBC DataFrame do Spark SQL.Wykrywanie java.sql.SQLException: Nie znaleziono odpowiedniego sterownika podczas ładowania DataFrame do Spark SQL

Próbowałem już kilka klastrów Spark - PRZEGLĄD, samodzielny klaster i tryb pseudo rozproszony na moim laptopie. Jest powtarzalny zarówno w Spark 1.3.0, jak i 1.3.1. Problem występuje zarówno w spark-shell, jak i podczas wykonywania kodu z spark-submit. Próbowałem MySQL & sterowników MS SQL JDBC bez powodzenia.

Rozważmy następujące próbki:

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

tej pory tak dobrze, schemat zostanie rozwiązany poprawnie:

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

Ale kiedy ocenia DataFrame: występuje

t1.take(1) 

następujący wyjątek:

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) 

Kiedy próbuję otworzyć JDBC połączenia na egzekutora:

import java.sql.DriverManager 

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

działa idealnie:

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

Kiedy uruchomić ten sam kod lokalny Spark, to działa doskonale także:

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

Używam Sparka fabrycznie z obsługą Hadoop 2.4.

Najprostszym sposobem odtworzenia problemu jest uruchomienie trybu Spark w pseudo rozprowadzany z start-all.sh skryptu i uruchomić następujące polecenie:

/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 

czy istnieje sposób do pracy to ok? Wygląda na poważny problem, więc dziwne, że nie pomaga tutaj szukanie w Google.

Odpowiedz

4

Najwyraźniej kwestia ta została niedawno:

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

Problem jest w java.sql.DriverManager że nie widzi sterowniki załadowane przez ClassLoaders innych niż bootstrap ClassLoader.

Jako tymczasowe obejście można dodać wymagane sterowniki, aby uruchomić ścieżkę klasy executorów.

UPDATE: Ta prośba przyciąganie rozwiązuje problemu: https://github.com/apache/spark/pull/5782

UPDATE 2: Poprawkę połączyły Spark 1.4

+0

Hej @Wildfire, jak poszedłeś o edycję ścieżki klasy startowy wykonawców? Próbowałem zmodyfikować ścieżkę kontenera YARN, aby dodać słoik mysql-connector-java, ale nie naprawił błędu. Dzięki! – JKnight

+1

@JKnight Nie mogłem wymyślić, jak dodać sterownik JDBC do bootowania ścieżki klasy na YARN, więc używam tylko poprawionej kompilacji Spark. – Wildfire

1

Utknęliśmy na Spark 1.3 (Cloudera 5,4) i tak znalazłem na to pytanie i odpowiedź Wildfire za pomocne, ponieważ pozwoliło mi przestać walić głową w ścianę.

Pomyślałem, że podzielę się tym, jak wprowadziliśmy sterownik do boot clathspath: po prostu skopiowaliśmy go do /opt/cloudera/parcels/CDH-5.4.0-1.cdh5.4.0.p0.27/lib/hive/lib na wszystkich węzłach.

+0

Witam, czy uruchomiłeś ponownie Cloudera po dodaniu sterownika do tego folderu? dzięki – SantiArias

+1

@SantiArias tak wierzę, że ponownie uruchomiliśmy klaster. –

3

Do zapisywania danych do MySQL

W iskry 1.4.0, trzeba załadować MySQL przed napisaniem do niego, ponieważ ładuje sterowniki w funkcji obciążenia, ale nie na funkcji zapisu. Musimy umieścić jar na każdym węźle roboczym i ustawić ścieżkę w iskrowym pliku defaultsconf na każdym węźle. Ten problem został rozwiązany w iskrą 1.5.0

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

0

Używam zapłonie 1.6.1 z serwera SQL, wciąż w obliczu tego samego problemu. Musiałem dodać bibliotekę (sqljdbc-4.0.jar) do biblioteki w instancji i poniżej linii w pliku conf/spark-dfault.conf.

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