【问题标题】:Spark Unable to find JDBC DriverSpark 找不到 JDBC 驱动程序
【发布时间】:2015-06-15 15:54:43
【问题描述】:

所以我一直在使用 sbt 和程序集来将我的所有依赖项打包到一个 jar 中以用于我的 spark 作业。我有几项工作,我使用c3p0 设置连接池信息,将其广播出去,然后在RDD 上使用foreachPartition 获取连接,并将数据插入数据库。在我的 sbt 构建脚本中,我包含了

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

这可确保 JDBC 连接器与作业打包在一起。一切都很好。

所以最近我开始使用 SparkSQL,并意识到使用 1.3.0 中的新功能将数据帧保存到 jdbc 源会更容易

我收到以下异常:

java.sql.SQLException:找不到合适的驱动程序 jdbc:mysql://some.domain.com/myschema?user=user&password=password at java.sql.DriverManager.getConnection(DriverManager.java:596) 在 java.sql.DriverManager.getConnection(DriverManager.java:233)

当我在本地运行它时,我通过设置绕过它

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

最终我想知道的是,为什么在应该打包的时候找不到驱动程序的工作?我的其他工作从来没有这个问题。据我所知,c3p0 和数据帧代码都使用了java.sql.DriverManager (它可以为您处理我所知道的所有内容),所以它应该可以正常工作?如果有什么东西阻止了组装方法的工作,我需要做什么才能使这个工作?

【问题讨论】:

  • 您如何开展工作?您是否检查过您组装的 jar 是否包含 MySQL 驱动程序?
  • 我确实检查了 jar,它确实包含 MySQL 驱动程序。我使用 bin/spark-submit --class "com.mypackage.MyJob" --verbose spark://place.where.this.exists.com:7077 MyJob.jar 启动我的工作
  • 我有同样的问题,也在尝试保存到mysql。你有没有追根究底?

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


【解决方案1】:

此人也有类似问题:http://apache-spark-user-list.1001560.n3.nabble.com/How-to-use-DataFrame-with-MySQL-td22178.html

您是否已将连接器驱动程序更新到最新版本?调用 load() 时也指定了驱动类吗?

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.cj.jdbc.Driver"); //here
DataFrame jdbcDF = sqlContext.load("jdbc", options); 

在spark/conf/spark-defaults.conf中,你也可以设置spark.driver.extraClassPath和spark.executor.extraClassPath为你的MySql驱动.jar的路径

【讨论】:

  • 将 jar 路径添加到 spark-defaults.conf,成功了! (如果失败,请尝试重新创建集群并添加 jar)
【解决方案2】:

spark docs:--driver-class-path postgresql-9.4.1207.jar --jars postgresql-9.4.1207.jar中明确提到了这些选项

我犯的错误是在我的应用程序的 jar 之后提到了这些选项。

但是正确的方法是在 spark-submit 之后立即指定这些选项:

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

【讨论】:

  • 你是救生员。谢谢
  • 我正在构建一个包含所有驱动程序类的 uber-jar。我还需要手动向驱动程序 jar 提供 spark-submit 命令吗?
  • 我假设如果您提供了一个主 jar,那么其中的所有 jar 都应该在类路径中可用。你试过这种方法吗?
  • 在向 EMR 提交作业时如何正确执行此操作?
  • 如果在 windows 上通过 spark-shell 使用,您可以按如下方式使用: spark-shell --driver-class-path "C:\Program Files\Microsoft JDBC Driver 6.0 for SQL Server\sqljdbc_6. 0\enu\jre8\sqljdbc42.jar" --jars "C:\Program Files\Microsoft JDBC Driver 6.0 for SQL Server\sqljdbc_6.0\enu\jre8\sqljdbc42.jar"
【解决方案3】:

spark驱动和执行器都需要类路径上的mysql驱动,所以要指定

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

【讨论】:

  • SparkSession.builder.config('spark.driver.extraClassPath', '/path/to/mysqlconnector.jar').config('spark.executor.extraClassPath', '/path/to/mysqlconnector.jar').getOrCreate()。如果您在已经创建了这样的会话之后尝试此操作(但没有 MySQL 连接器 jar 的配置),那么如果您通过它使用 spark,则重新启动您的 all-spark-notebook Docker 容器,然后重试构建 spark 会话,包括配置语句。
【解决方案4】:

使用 spark 2.2.0,我通过在 python 脚本中为 SparkSession 会话添加额外的类路径信息来纠正问题:

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

见官方文档https://spark.apache.org/docs/latest/configuration.html

在我的例子中,spark 不是从 cli 命令启动,而是从 django 框架https://www.djangoproject.com/

【讨论】:

  • 知道在向 Amazon EMR 提交作业时这是否可行?
【解决方案5】:

spark.driver.extraClassPath 在客户端模式下不起作用:

注意:在客户端模式下,这个配置不能直接在你的应用程序中通过 SparkConf 设置,因为此时驱动程序 JVM 已经启动。相反,请通过 --driver-class-path 命令行选项或在您的默认属性文件中进行设置。

环境变量 SPARK_CLASSPATH 在 Spark 1.0+ 中已被弃用。

您应该首先将 jdbc 驱动程序 jar 复制到同一本地文件系统路径下的每个执行程序中,然后在 spark-submit 中使用以下选项:

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

例如,对于 TeraData,您需要 terajdbc4.jar 和 tdgssconfig.jar。

或者修改所有工作节点上的 compute_classpath.sh,Spark 文档说:

JDBC 驱动程序类必须对客户端会话和所有执行程序上的原始类加载器可见。这是因为 Java 的 DriverManager 类进行了一项安全检查,导致它在打开连接时忽略原始类加载器不可见的所有驱动程序。一种方便的方法是修改所有工作节点上的 compute_classpath.sh 以包含您的驱动程序 JAR。

【讨论】:

    【解决方案6】:

    有一个简单的 Java 技巧可以解决您的问题。您应该指定Class.forName() 实例。例如:

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

    查看docs

    【讨论】:

    • 在 Scala 中我使用了: new JdbcRDD(sc, () => { Class.forName(driverName).newInstance; DriverManager.getConnection(url, user, password) }, "SELECT * FROM stats_20151230" , 0, 0, 1) 谢谢!
    【解决方案7】:

    简单的方法是将“mysql-connector-java-5.1.47.jar”复制到“spark-2.4.3\jars\”目录中

    【讨论】:

      【解决方案8】:

      我在集群模式下通过 Mesos 集群运行作业时遇到了同样的问题。

      要使用 JDBC 驱动程序,必须将依赖项添加到系统类路径而不是框架类路径。我只是通过在集群的每个实例中添加文件spark-defaults.conf 中的依赖项来找到这样做的方法。

      要添加的属性是spark.driver.extraClassPathspark.executor.extraClassPath,并且路径必须在本地文件系统中。

      【讨论】:

      • 我在这里尝试了所有解决方案,没有任何效果,我不断收到“没有合适的驱动程序”错误。想法?
      【解决方案9】:

      我将jar文件添加到spark-env.sh中的SPARK_CLASSPATH,它可以工作。

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

      【讨论】:

        【解决方案10】:

        当我尝试从我的 Windows 机器运行 spark-shell 命令时,我遇到了同样的问题。您为驱动程序位置以及您将使用的 jar 传递的路径应该用双引号括起来,否则它会被误解,并且您将无法获得所需的确切输出。

        您还必须通过以下链接为 SQL 服务器安装 JDBC 驱动程序:JDBC Driver

        我已使用以下命令在我的 Windows 机器上正常工作:

        spark-shell --driver-class-path "C:\Program Files\Microsoft JDBC Driver 6.0 for SQL Server\sqljdbc_6.0\enu\jre8\sqljdbc42.jar" --jars "C:\ Program Files\Microsoft JDBC Driver 6.0 for SQL Server\sqljdbc_6.0\enu\jre8\sqljdbc42.jar"

        【讨论】:

        • 您能否将链接的图像更改为实际链接到图像中的链接?只需粘贴 URL 就足够了 - 根本不需要任何图像。 :)
        猜你喜欢
        • 1970-01-01
        • 2016-01-10
        • 2016-04-18
        • 2017-07-21
        • 2013-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多