Hive 事务崩溃

Hive Transactions are crashing

好的,这几天我一直在处理这个问题,这让我抓狂。我需要使用带有事务的 Hive 数据库来执行 'update' 和 'delete' 操作。

我已经在我的机器上以伪分布式方式安装了Hadoop 和Hive。我已经按照这个 tutorial 安装了。我正在使用 Java 1.8.0_31、Hadoop 2.6.0、Hive 1.0.0,我还更改了一些细节,但这些应该不相关。

现在,要启动我的环境(例如,重启后),我 运行 以下内容:

start-dfs.sh
start-yarn.sh
java -jar /usr/local/derby/lib/derbyrun.jar server start &
hive

而且似乎一切正常。虽然教程没有提到启动 derby,但如果我不启动它,Metastore 将不可用(这似乎合乎逻辑)并且配置单元不会启动。

从这里,我可以创建表格、显示表格、连接我的 JDBC 客户端等等,一切都很好。现在,我需要启用交易。按照这个 link and this link 我得到以下命令:

hive --hiveconf hive.root.logger=info,console 
    --hiveconf hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager 
    --hiveconf hive.compactor.initiator.on=true 
    --hiveconf hive.compactor.worker.threads=1 
    --hiveconf hive.txn.driver=jdbc:derby://localhost:1527/metastore_db;create=true

旁注:我正在更改命令而不是 hive-site.xml 只是因为在尝试有效和无效时更容易在命令之间切换而不是重复更改 XML文件。

我也曾尝试将驱动程序 url 更改为 jdbc:derby://localhost:1527/metastore_db;create=true;user=APP;password=mine 以备不时之需,但没有任何改变。当我发出命令(如 show tables)时,出现错误:

15/03/04 23:26:17 [main]: ERROR metastore.RetryingHMSHandler: 
    MetaException(message:Unable to select from transaction database, 
    java.sql.SQLSyntaxErrorException: Table/View 'TXNS' does not exist.

根据 this and one of the previous links,似乎 hive.in.test 属性 必须设置为 true。所以,我的启动命令变成:

hive --hiveconf hive.root.logger=info,console 
    --hiveconf hive.in.test=true 
    --hiveconf hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager 
    --hiveconf hive.compactor.initiator.on=true 
    --hiveconf hive.compactor.worker.threads=1 
    --hiveconf hive.txn.driver=jdbc:derby://localhost:1527/metastore_db;create=true;

使用这个命令,我得到一个新的错误:

ERROR metastore.RetryingHMSHandler: java.lang.NullPointerException
    at org.apache.hadoop.hive.metastore.txn.TxnHandler.checkQFileTestHack(TxnHandler.java:1146)

而且这个错误在任何地方都不存在,我觉得我是互联网上唯一遇到它的人。无论如何,因为我找不到任何解决方案,所以我研究了源代码:

private void checkQFileTestHack() {
  boolean hackOn = HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_IN_TEST) ||
    HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_IN_TEZ_TEST);

  LOG.info("Before if");
  if (hackOn) {
      LOG.info("Hacking in canned values for transaction manager");
      // Set up the transaction/locking db in the derby metastore
      TxnDbUtil.setConfValues(conf);
      try {
          TxnDbUtil.prepDb();
      } catch (Exception e) {
          // We may have already created the tables and thus don't need to redo it.
          if (!e.getMessage().contains("already exists")) {
              throw new RuntimeException("Unable to set up transaction database for" +
                " testing: " + e.getMessage());
          }
      }
  }
}

1146 行是if (!e.getMessage().contains("already exists")) 行,这似乎没有多大意义,除非"e" 为null,这很奇怪。无论如何,我想我可以通过添加更多日志消息、构建项目并替换我修改过的原始 Metastore jar(这是这个 TxnHandler class 所在的位置)来进一步调试它。为此,我下载了源代码并按照 this to build it. I tried maven2 and it didn't work, because some plug-in only worked with maven3, so I got maven3 from here 构建了项目。

如果我使用 mvn clean install -Phadoop-2,dist 命令构建它,不仅需要很长时间,而且在测试阶段会失败。因为它不会在 Metastore 上失败(在 Metastore 上,它会跳过 1 次测试,我不确定这是否应该发生),我想我可以在没有测试的情况下构建它。所以,我们得到这个:

mvn clean install -DskipTests -Phadoop-2,dist
rm /usr/local/hive/lib/hive-metastore-1.0.0.jar
cp packaging/target/apache-hive-1.0.0-bin/apache-hive-1.0.0-bin/lib/hive-metastore-1.0.0.jar /usr/local/hive/lib/

旁注:为了节省时间,我也尝试了 -pl metastore -am 参数,但是虽然 maven 说 metastore 已经构建,但 lib 文件夹中的 jar 没有改变,所以我猜我我做错了什么。

无论如何,这应该构建我修改后的 jar,替换配置单元中的那个,当我再次启动配置单元时,它应该加载我的。然而,即使我更改了代码,错误仍然显示相同,我的新日志信息未注册,即使错误行保持不变。就好像我在我的新罐子里什么也没改变。

奇怪,我知道 maven 正在编译我的代码,因为它可以识别编译错误,而且我可以在 jar 属性上看到它是一个新文件,那么为什么我的其余更改没有显示出来?当我删除原始 jar 时,Hive 会识别,但是当我用修改后的版本替换它时,它就像我什么也没改变一样。

无论如何,如您所见,我遇到了很多麻烦,并且我已尝试解决其中的大部分问题。但是现在我陷入了这个,无法使用该死的 "delete" 命令,因为我无法启用交易。谁能指出我正确的方向? Tyvm!

...很抱歉 post.

我按照 Srinivas 的 advice 进行了操作,错误消失了。我不再需要 "hive.in.test" 属性 设置为 "true" 并且一切正常。

我仍然不知道为什么更改源不会影响 hive 程序的其余部分,但我有事务工作。

编辑:以防 link 出现故障,这里引用一句话:

After extracting Hive version, you have to create Hive meta store

sudo apt-get install mysql-server
sudo service mysql start
sudo apt-get install libmysql-java
ln -s /usr/share/java/libmysql-java.jar /usr/lib/hive/lib/libmysql-java.jar
sudo chkconfig mysql on

mysql -u root -p
Enter password:
mysql> CREATE DATABASE metastore;
mysql> USE metastore;
mysql> SOURCE /usr/lib/hive/scripts/metastore/upgrade/mysql/hive-schema-0.12.0.mysql.sql;

mysql> CREATE USER 'hive'@'metastorehost' IDENTIFIED BY 'mypassword';
...
mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'hive'@'metastorehost';
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,LOCK TABLES,EXECUTE ON metastore.* TO 'hive'@'metastorehost';
mysql> FLUSH PRIVILEGES;
mysql> quit;

Then in hive-site.xml, you need set the new parameters like

javax.jdo.option.ConnectionURL - jdbc:mysql://myhost/metastore
javax.jdo.option.ConnectionDriverName - com.mysql.jdbc.Driver
javax.jdo.option.ConnectionUserName - hive
javax.jdo.option.ConnectionPassword - mypassword
datanucleus.autoCreateSchema - false
datanucleus.fixedDatastore - true
datanucleus.autoStartMechanism - SchemaTable
hive.metastore.uris - thrift://<n.n.n.n>:9083

hive.support.concurrency – true  
hive.enforce.bucketing – true 
hive.exec.dynamic.partition.mode – nonstrict  
hive.txn.manager – org.apache.hadoop.hive.ql.lockmgr.DbTxnManager 
hive.compactor.initiator.on – true  
hive.compactor.worker.threads – 1

Then restart Hive-server and Metastore. Now create one normal table and one external table with orc format and load from normal to orc table. Now you can update and delete records.