1. 程式人生 > >Hive 併發情況下報 DELETEME 表不存在的異常

Hive 併發情況下報 DELETEME 表不存在的異常

在每天執行的Hive指令碼中,偶爾會丟擲以下錯誤:

2013-09-03 01:39:00,973 ERROR parse.SemanticAnalyzer (SemanticAnalyzer.java:getMetaData(1128)) - org.apache.hadoop.hive.ql.metadata.HiveException: Unable to fetch table dw_xxx_xxx
        at org.apache.hadoop.hive.ql.metadata.Hive.getTable(Hive.java:896)
        ...
Caused by: javax.jdo.JDODataStoreException: Exception thrown obtaining schema column information from datastore
NestedThrowables:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'hive.DELETEME1378143540925'
doesn't exist at org.datanucleus.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:313) ...

查閱了網上的資料,是DataNucleus的問題。

背景1:我們知道MySQL中的庫表資訊是存放在information_schema庫中的,Hive也有類似的機制,它會將庫表資訊存放在一個第三方的RDBMS中,目前我們線上配置的是本機MySQL,即:

$ mysql -uhive -ppassword hive

1.png

背景2:Hive使用的是DataNuclues ORM庫來操作資料庫的,而基本上所有的ORM框架(物件關係對映)都會提供自動建表的功能,即開發者只需編寫Java物件,ORM會自動生成DDL。DataNuclues也有這一功能,而且它在初始化時會通過生成臨時表的方式來獲取資料庫的Catalog和Schema,也就是 DELETEME表:

2.png

這樣就有一個問題:在併發量大的情況下,DELETEME表名中的毫秒數可能相同,那在pt.drop(conn)的時候就會產生找不到表的報錯。

解決辦法已經可以在程式碼中看到了:將datanucleus.fixedDataStore選項置為true,即告知DataNuclues該資料庫的表結構是既定的,不允許執行DDL操作。

這樣配置會有什麼問題?讓我們回憶一下Hive的安裝步驟:

  1. 解壓hive-xyz.tar.gz;
  2. 在conf/hive-site.xml中配置Hadoop以及用於存放庫表資訊的第三方資料庫;
  3. 執行bin/hive -e “…”即可使用。DataNucleus會按需建立上述的DBS等表。

這對新手來說很有用,因為不需要手動去執行建表語句,但對生產環境來說,普通帳號是沒有DDL許可權的,我們公司建表也都是提DB-RT給DBA操作。同理,線上Hive資料庫也應該採用手工建立的方式,匯入scripts/metastore/upgrade/mysql/hive-schema-0.9.0.mysql.sql檔案即可。這樣一來,就可以放心地配置datanucleus.fixedDataStore以及 datanecleus.autoCreateSchema兩個選項了。

這裡我們也明確了一個問題:設定datanucleus.fixedDataStore=true不會影響Hive建庫建表,因為Hive中的庫表只是DBS、TBLS表中的一條記錄而已。

建議的操作:

  1. 在線上匯入hive-schema-0.9.0.mysql.sql,將尚未建立的表建立好(比如我們沒有用過Hive的許可權管理,所以DataNucleus沒有自動建立DB_PRIVS表);
  2. 在hive-site.xml中配置 datanucleus.fixedDataStore=true;datanecleus.autoCreateSchema=false。

這樣就可以徹底解決這個異常了。

為什麼HWI沒有遇到類似問題?因為它是常駐記憶體的,DELETEME表只會在啟動的時候建立,後續的查詢不會建立。而我們這裡每次呼叫hive命令列都會去建立,所以才有這樣的問題。

參考連結: