2017-04-21 65 views
0

我已經在自己的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底層基礎架構時,你會得到相同的堆棧跟蹤。 –

回答

1

錯誤消息:

產生的原因: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

0

感謝來自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()

是的,我知道這很髒。使用風險自負。

相關問題