Amazon EMR w/Spark w/Postgres:“无法启动数据库'metastore_db'”

问题描述:

我已经在自己的Linux服务器上使用Apache Spark和PostgreSQL JDBC驱动程序,但没有问题,但我无法使其工作在Amazon EMR上以同样的方式执行。Amazon EMR w/Spark w/Postgres:“无法启动数据库'metastore_db'”

我先下载Postgres的驱动程序和设置我pyspark类路径是这样的:Adding postgresql jar though spark-submit on amazon EMR

我执行在Amazon EMR实例设置了Spark在pyspark下,类似于如何我通常做我自己服务器。 “myhost的”正在运行的PostgreSQL,这我能够从我的EMR实例与psql连接到我的亚马逊RDS实例的主机名,所以我知道它应该工作:

# helper, gets RDD from database 
def get_db_rdd(table, lower=0, upper=1000): 
    db_connection = { 
      "host": "myhost", 
      "port": 5432, 
      "database": "mydb", 
      "user": "postgres", 
      "password": "mypassword" 
      } 
    url = "jdbc:postgresql://{}:{}/{}?user={}".format(db_connection["host"], 
                 db_connection["port"], 
                 db_connection["database"], 
                 db_connection["user"]) 
    ret = sqlContext \ 
     .read \ 
     .format("jdbc") \ 
     .option("url", url) \ 
     .option("dbtable", table) \ 
     .option("partitionColumn", "id") \ 
     .option("numPartitions", 1024) \ 
     .option("lowerBound", lower) \ 
     .option("upperBound", upper) \ 
     .option("password", db_connection["password"]) \ 
     .load() 
    ret = ret.rdd 
    return ret 

from pyspark.sql import SQLContext 
sqlContext = SQLContext(sc) 

rdd = get_db_rdd("test", 0, 3) # table exists, has columns (`id bigserial, string text`) 

我立即得到一个崩溃与此异常:

17/04/21 19:34:07 ERROR Schema: Failed initialising database. 
Unable to open a test connection to the given database. JDBC url = jdbc:derby:;databaseName=metastore_db;create=true, username = APP. Terminating connection pool (set lazyInit to true if you expect to start your database after your app). Original Exception: ------ 
java.sql.SQLException: Failed to start database 'metastore_db' with class loader [email protected]a157b0, see the next exception for details. 
     at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source) 
     at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source) 
[...] 

环顾在线,这与Apache Hive有关...不知道为什么这里涉及到,但我可能会误解。我在我的家里看到metastore_db。所有提出的解决方案都涉及到编辑一些Hive配置,我甚至没有在我的实例上创建该配置或创建该目录。我的EMR实例具有完全默认设置。更熟悉这种环境的人能否指出我正确的方向?

编辑:我没有整个堆栈跟踪方便,但有一些留在我的GNU屏幕。下面是更多的,提到德比:

Caused by: ERROR XJ040: Failed to start database 'metastore_db' with class loader [email protected]a157b0, see the next exception for details. 
     at org.apache.derby.iapi.error.StandardException.newException(Unknown Source) 
     at org.apache.derby.impl.jdbc.SQLExceptionFactory.wrapArgsForTransportAcrossDRDA(Unknown Source) 
     ... 113 more 
Caused by: ERROR XSDB6: Another instance of Derby may have already booted the database /home/hadoop/metastore_db. 
     at org.apache.derby.iapi.error.StandardException.newException(Unknown Source) 
     at org.apache.derby.iapi.error.StandardException.newException(Unknown Source) 
     at org.apache.derby.impl.store.raw.data.BaseDataFileFactory.privGetJBMSLockOnDB(Unknown Source) 

编辑2:使用其他RDDS像以下工作:sc.parallelize([1, 2, 3]).map(lambda r: r * 2).collect()。问题仅在于连接到Postgres的RDD。

编辑3:

>>> spark.range(5).show() 
+---+ 
| id| 
+---+ 
| 0| 
| 1| 
| 2| 
| 3| 
| 4| 
+---+ 
+2

“无法启动数据库'metastore_db'”通常在您已经有一个Spark实例正在运行时发生,并且默认Metastore在封面下使用Derby,因此是异常。你能发布整个堆栈跟踪吗?我期望Derby的错误落在堆栈跟踪的底部。 –

+1

是的,我看到德比的错误。但据我所知,我只有一个Spark实例在运行。星期一,我会再试一次,并捕获整个堆栈跟踪。 – sudo

+0

变得更好!认为我们可以尽快整理出来。我相信当你仅仅使用'spark-shell'并执行'spark.range(5).show'并且启动Spark底层基础架构时,你会得到相同的堆栈跟踪。 –

错误消息:

产生的原因:ERROR XSDB6:德比的另一个实例可能已经启动了数据库/家庭/ Hadoop的/ metastore_db。

告诉我们嵌入式单线程Derby实例已经在使用中。我不是很熟悉的蜂巢,但星火靴子蜂房启用SparkSession在使用,你可以在你的堆栈跟踪看到:

at org.apache.hadoop.hive.ql.session.SessionState.start(SessionState.java:503) 
    at org.apache.spark.sql.hive.client.HiveClientImpl.<init>(HiveClientImpl.scala:192) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
    at org.apache.spark.sql.hive.client.IsolatedClientLoader.createClient(IsolatedClientLoader.scala:264) 
    at org.apache.spark.sql.hive.HiveUtils$.newClientForMetadata(HiveUtils.scala:366) 
    at org.apache.spark.sql.hive.HiveUtils$.newClientForMetadata(HiveUtils.scala:270) 
    at org.apache.spark.sql.hive.HiveExternalCatalog.<init>(HiveExternalCatalog.scala:65) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
    at org.apache.spark.sql.internal.SharedState$.org$apache$spark$sql$internal$SharedState$$reflect(SharedState.scala:166) 
    at org.apache.spark.sql.internal.SharedState.<init>(SharedState.scala:86) 
    at org.apache.spark.sql.SparkSession$$anonfun$sharedState$1.apply(SparkSession.scala:101) 
    at org.apache.spark.sql.SparkSession$$anonfun$sharedState$1.apply(SparkSession.scala:101) 
    at scala.Option.getOrElse(Option.scala:121) 
    at org.apache.spark.sql.SparkSession.sharedState$lzycompute(SparkSession.scala:101) 
    at org.apache.spark.sql.SparkSession.sharedState(SparkSession.scala:100) 
    at org.apache.spark.sql.internal.SessionState.<init>(SessionState.scala:157) 
    at org.apache.spark.sql.hive.HiveSessionState.<init>(HiveSessionState.scala:32) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
    at org.apache.spark.sql.SparkSession$.org$apache$spark$sql$SparkSession$$reflect(SparkSession.scala:978) 
    at org.apache.spark.sql.SparkSession.sessionState$lzycompute(SparkSession.scala:110) 
    at org.apache.spark.sql.SparkSession.sessionState(SparkSession.scala:109) 
    at org.apache.spark.sql.DataFrameReader.<init>(DataFrameReader.scala:549) 
    at org.apache.spark.sql.SparkSession.read(SparkSession.scala:605) 
    at org.apache.spark.sql.SQLContext.read(SQLContext.scala:516) 

我复制了最相关的线(去除噪声)。注意:由于Spark本身支持最多(并且在Spark 2.2最为Hive“基础架构”will get away),因此近期您并不需要Hive特性。

正如您在堆栈跟踪中看到的那样,当您使用作为Spark SQL入口点的SparkSession时,将只会抛出多线程访问单线程Derby异常。

at org.apache.spark.sql.SparkSession.sessionState$lzycompute(SparkSession.scala:110) 
    at org.apache.spark.sql.SparkSession.sessionState(SparkSession.scala:109) 
    at org.apache.spark.sql.DataFrameReader.<init>(DataFrameReader.scala:549) 
    at org.apache.spark.sql.SparkSession.read(SparkSession.scala:605) 
    at org.apache.spark.sql.SQLContext.read(SQLContext.scala:516) 

这就是为什么在使用RDD API时看不到它的原因。 RDD API根本不使用Hive。

阅读Hive的官方文档Local/Embedded Metastore Database (Derby)

+0

是的,问题是Amazon在build/config中默认包含Hive。似乎我可以避免这个问题,如果我禁用Hive或断开默认连接,然后再为Postgres设置我的SQLContext。文档不建议任何方式来做到这一点。我尝试'del sqlContext'使原始Hive上下文'pyspark'创建断开连接,没有运气。 – sudo

感谢来自Jacek的关于我的问题性质的建议,经过一些试验和错误之后,我开发了一个黑客解决方法。还没有能够真正解决问题,但这是有效的,这对我来说已经足够了。如果我稍后遇到问题,我会报告。 (!):

  1. 与Postgres的驱动程序的正常启动pyspark pyspark --driver-class-path=/home/hadoop/postgres_driver.jar --jars=/home/hadoop/postgres_driver.jar

  2. 虽然这是开放的,在一个单独的SSH会话,cd到家庭和mv metastore_db old_metastore_db(或者你可以在pyspark与os.system()做到这一点)。重点是释放Spark默认创建的Metastore上的锁定; Spark将重新创建没有锁定的目录。

  3. 尝试按照我在问题中描述的方式创建连接到Postgres的RDD。它会给出一个关于“没有合适的驱动程序”的错误。出于某种原因,该驱动程序未加载。但是在那个错误之后,看起来驱动程序实际上已经加载了。

  4. mv metastore_db old_metastore_db2,出于与上述类似的原因。我想现在连接了另一个Hive会话,需要清除锁定。

  5. 以同样的方式再次创建Postgres连接的RDD。驱动程序已加载,并且Metastore已解锁,并且似乎正常工作。我可以从我的表中获取,执行RDD操作,并且collect()

是的,我知道这很脏。使用风险自负。