2015-04-10 20 views
19

So habe ich sbt mit Assembly verwendet, um alle meine Abhängigkeiten in einem einzigen Glas für meine Spark-Jobs zu packen. Ich habe mehrere Jobs, wo ich c3p0 verwendet, um Verbindungspool-Informationen einzurichten, diese auszustrahlen und dann foreachPartition auf dem RDD zu verwenden, um dann eine Verbindung aufzunehmen und die Daten in die Datenbank einzufügen. In meinem sbt Build-Skript, schließe ichSpark JDBC-Treiber konnte nicht gefunden werden

"mysql" % "mysql-connector-java" % "5.1.33" 

Dies ist der JDBC-Connector stellt sicher, dass mit dem Job verpackt werden. Alles funktioniert super.

So vor kurzem begann ich um mit SparkSQL spielen und erkennen, dass es viel einfacher ist, einfach einen Datenrahmen zu nehmen und es zu einer JDBC-Quelle mit den neuen Funktionen in 1.3.0

speichert Ich erhalte die folgende Ausnahme:

java.sql.SQLException: Nein für geeignet befundene Treiber jdbc: mysql: //some.domain.com/myschema user = user & password = Passwort bei java.sql.DriverManager.getConnection (DriverManager.java: 596) um java.sql.DriverManager.getConnection (Laufwerk rManager.java:233)

Als ich laufen diese lokal habe ich es um, indem

SPARK_CLASSPATH=/path/where/mysql-connector-is.jar 

Letztlich ist zu wissen, was ich will, warum ist die Aufgabe nicht in der Lage das zu finden, Treiber, wenn es damit verpackt werden soll? Meine anderen Jobs hatten dieses Problem nie. Von dem, was ich sagen kann c3p0 und der Dataframe-Code beide verwenden Sie die java.sql.DriverManager (die alles für Sie importiert von dem, was ich sagen kann importieren), so sollte es gut funktionieren ?? Wenn etwas verhindert, dass die Assembly-Methode funktioniert, was muss ich tun, damit dies funktioniert?

+0

Wie Sie Ihre Jobs starten Sie? Haben Sie überprüft, ob Ihr assemblierter Jar den MySQL-Treiber enthält? –

+0

Ich habe das Jar überprüft, es enthält den MySQL-Treiber. Ich starte meinen Job mit bin/spark-submit --class "com.mypackage.MyJob" --verbose funken: //place.where.this.exists.com: 7077 MyJob.jar –

+0

Ich habe das gleiche Problem, auch versuchen in mysql speichern. Ist dir das jemals auf den Grund gegangen? – Marcin

Antwort

21

Diese Person ähnliches Problem hatte: http://apache-spark-user-list.1001560.n3.nabble.com/How-to-use-DataFrame-with-MySQL-td22178.html

Sie Ihren Anschluss Treiber auf die neueste Version aktualisiert haben? Haben Sie beim Aufruf von load() auch die Treiberklasse angegeben?

Map<String, String> options = new HashMap<String, String>(); 
options.put("url", "jdbc:mysql://localhost:3306/video_rcmd?user=root&password=123456"); 
options.put("dbtable", "video"); 
options.put("driver", "com.mysql.jdbc.Driver"); //here 
DataFrame jdbcDF = sqlContext.load("jdbc", options); 

In Funken/conf/Funken defaults.conf, können Sie auch spark.driver.extraClassPath und spark.executor.extraClassPath auf den Pfad Ihres MySql Treibersetz- .jar

+3

Vielen Dank für Ihr "// hier" !!! – beloblotskiy

+0

Vielen Dank für den Zeiger "// hier" –

3

Es existiert eine einfache Java-Trick, um dein Problem zu lösen. Sie sollten Class.forName() Instanz angeben. Zum Beispiel: die

val customers: RDD[(Int, String)] = new JdbcRDD(sc,() => { 
     Class.forName("com.mysql.jdbc.Driver") 
     DriverManager.getConnection(jdbcUrl) 
     }, 
     "SELECT id, name from customer WHERE ? < id and id <= ?" , 
     0, range, partitions, r => (r.getInt(1), r.getString(2))) 

prüfen docs

+0

In Scala habe ich verwendet: neue JdbcRDD (sc,() => {Class.forName (driverName) .newInstance; DriverManager.getConnection (URL, Benutzer, Passwort)}, " SELECT * FROM stats_20151230 ", 0, 0, 1) Danke! – beloblotskiy

12

Beide Funken Fahrer und Vollstrecker muss Fahrer auf Klassenpfad mysql so angeben

spark.driver.extraClassPath = <path>/mysql-connector-java-5.1.36.jar 
spark.executor.extraClassPath = <path>/mysql-connector-java-5.1.36.jar 
+0

Mit Python löste dies das Problem für mich – Sean

6

spark.driver.extraClassPath nicht in Client-Modus funktioniert:

Hinweis: im Client-Modus muss diese Konfiguration nicht durch die SparkConf direkt in Ihren Anwen eingestellt wird Kation, weil der Fahrer JVM bereits an diesem Punkt gestartet hat. Setzen Sie dies stattdessen über die Befehlszeilenoption --driver-class-path oder in der Standardeigenschaftendatei.

Die Env-Variable SPARK_CLASSPATH wurde in Spark 1.0+ als veraltet eingestuft.

Sie sollten die JDBC-Treiber Gläser in jeden Testamentsvollstrecker unter dem gleichen lokalen Dateisystem-Pfad und verwenden Sie dann die folgenden Optionen in Ihnen Funken einreichen erstes kopieren:

--driver-class-path "driver_local_file_system_jdbc_driver1.jar:driver_local_file_system_jdbc_driver2.jar" 
--class "spark.executor.extraClassPath=executors_local_file_system_jdbc_driver1.jar:executors_local_file_system_jdbc_driver2.jar" 

Zum Beispiel im Fall von Teradata Sie beide terajdbc4 brauchen .jar und tdgssconfig.jar.

Alternativ ändern compute_classpath.sh auf alle Arbeiter Knoten, Funken Dokumentation sagt:

Der JDBC-Treiber-Klasse auf die Ur-Class-Loader auf dem Client-Sitzung und auf allen Testamentsvollstrecker sichtbar sein muss. Dies liegt daran, dass die DriverManager-Klasse von Java eine Sicherheitsprüfung durchführt, die dazu führt, dass alle Treiber ignoriert werden, die für den ursprünglichen Klassenlader beim Öffnen einer Verbindung nicht sichtbar sind. Eine praktische Möglichkeit besteht darin, compute_classpath.sh für alle Worker-Knoten so zu ändern, dass die Treiber-JARs enthalten sind.

1

Ich hatte das gleiche Problem beim Ausführen von Jobs über einen Mesos-Cluster im Cluster-Modus.

Die Verwendung eines JDBC-Treibers ist erforderlich, um die Abhängigkeit zum Systemklassenpfad nicht zum Frameworkklassenpfad hinzuzufügen. Ich habe den Weg nur gefunden, indem ich die Abhängigkeit in der Datei spark-defaults.conf in jeder Instanz des Clusters hinzugefügt habe. Die hinzuzufügenden Eigenschaften sind spark.driver.extraClassPath und spark.executor.extraClassPath und der Pfad muss sich im lokalen Dateisystem befinden.

+0

Ich versuchte alle Lösungen hier, nichts funktioniert, ich bekomme "kein passender Treiber" Fehler. Ideen? – thebeancounter

1

Ich füge die JAR-Datei zum SPARK_CLASSPATH in spark-env.sh, es funktioniert.

spark = SparkSession \ 
     .builder \ 
     .appName("Python Spark SQL basic example") \ 
     .config("spark.driver.extraClassPath", "/path/to/jdbc/driver/postgresql-42.1.4.jar") \ 
     .getOrCreate() 

Siehe offizielle Dokumentation https://spark.apache.org/docs/latest/configuration.html

In meinem Fall:

export SPARK_CLASSPATH=$SPARK_CLASSPATH:/local/spark-1.6.3-bin-hadoop2.6/lib/mysql-connector-java-5.1.40-bin.jar 
0

Mit Funken 2.2.0 wurde Problem für mich, Informationen durch das Hinzufügen zusätzliche Klassenpfad für SparkSession Sitzung in Python-Skript korrigiert funke wird nicht vom cli-Befehl gestartet, sondern vom django framework https://www.djangoproject.com/

2

Diese Optionen werden ineindeutig erwähnt: --driver-class-path postgresql-9.4.1207.jar --jars postgresql-9.4.1207.jar

Der Fehler, den ich machte, war, diese Optionen nach meiner Anwendung zu erwähnen.

jedoch der richtige Weg ist, diese Optionen festlegen unmittelbar nach Funken einreichen:

spark-submit --driver-class-path /somepath/project/mysql-connector-java-5.1.30-bin.jar --jars /somepath/project/mysql-connector-java-5.1.30-bin.jar --class com.package.MyClass target/scala-2.11/project_2.11-1.0.jar

+0

Sie sind ein Lebensretter. Danke –

+0

Ich baue ein Uber-Glas mit allen Fahrer Klasse drin. Muss ich den Treiber-Jar mit dem Befehl "Spark Submit" noch manuell bereitstellen? – Abhi

+0

Ich nehme an, wenn Sie einen Master-Jar zur Verfügung gestellt haben, dann sollten alle darin enthaltenen Gläser im Klassenpfad verfügbar sein. Hast du diesen Ansatz versucht? –

Verwandte Themen