• hbase源码分析:ERROR: Table already exists问题诊断


    问题描述:

    重新安装了测试环境的hadoop,所以之前hbase所建的表数据都丢失了,但是zookeeper没有动。在hbase shell中list的时候,看不到之前建的表,但是create test table的时候,却报错提示"ERROR: Table already exists: test!". 

    问题追踪:

    1,在list的时候,没有显示之前建的表,也就是没有感知到之前建的表,但是create时候却感知到了之前建的表,所以很自然需要看一下list和create的时候,server执行的逻辑。只要清楚了这个逻辑,问题便一清二楚了。

    2,list时server端的逻辑其实很简单。list的时候master端执行的逻辑的入口函数是listTableDescriptors。核心代码如下:

      

     1         // request for all TableDescriptors
     2         Collection<HTableDescriptor> htds;
     3         if (namespace != null && namespace.length() > 0) {
     4           htds = tableDescriptors.getByNamespace(namespace).values();
     5         } else {
     6           htds = tableDescriptors.getAll().values();
     7         }
     8 
     9         for (HTableDescriptor desc: htds) {
    10           if (includeSysTables || !desc.getTableName().isSystemTable()) {
    11             descriptors.add(desc);
    12           }
    13         }

    可以看到是从tableDescriptors中获取的,而tableDescriptors是根据hbase在hdfs中路径的描述

    1     this.tableDescriptors = new FSTableDescriptors(
    2       this.conf, this.fs, this.rootDir, !canUpdateTableDescriptor(), false);

    然后可以看到这些信息是从hbase在hdfs中的rootpath下的data目录中获取表相关信息的。所以,list的时候当然看不见之前的表了。

    3,create table的时候,在server端最终会使用createTableHandler或者createTableProcedure来处理建表的逻辑。在createTableProcedure中正式建表之前,会调用prepareCreate函数。

     1 private boolean prepareCreate(final MasterProcedureEnv env) throws IOException {
     2     final TableName tableName = getTableName();
     3     if (MetaTableAccessor.tableExists(env.getMasterServices().getConnection(), tableName)) {
     4       setFailure("master-create-table", new TableExistsException(getTableName()));
     5       return false;
     6     }
     7     // During master initialization, the ZK state could be inconsistent from failed DDL
     8     // in the past. If we fail here, it would prevent master to start.  We should force
     9     // setting the system table state regardless the table state.
    10     boolean skipTableStateCheck =
    11         !(env.getMasterServices().isInitialized()) && tableName.isSystemTable();
    12     if (!skipTableStateCheck) {
    13       TableStateManager tsm = env.getMasterServices().getAssignmentManager().getTableStateManager();
    14       if (tsm.isTableState(tableName, true, ZooKeeperProtos.Table.State.ENABLING,
    15           ZooKeeperProtos.Table.State.ENABLED)) {
    16         LOG.warn("The table " + tableName + " does not exist in meta but has a znode. " +
    17                "run hbck to fix inconsistencies.");
    18         setFailure("master-create-table", new TableExistsException(getTableName()));
    19         return false;
    20       }
    21     }
    22     return true;
    23   }

    在14行,通过TableStateManager会检查zookeeper对应的表状态是不是enable的,检查zk中的路径是hbase root path下的table目录。由于zk还是之前的zk,所以之前建的表信息还在,很自然这时候会检查已经存在,如是报了Table already exits的错误。Log提示中说用hbck去检查,但是貌似检查不出来是不一致的。

    问题解决:

    本来想通过hbck去检查,然后修复的,但是貌似hbck检查不出来。所以只是简单暴力的把zk中对应的table删除,然后create就没问题了。

  • 相关阅读:
    jQuery同步Ajax带来的UI线程阻塞问题及解决办法
    jQuery的deferred对象详解
    原生js,jquery ajax请求以及jsonp的调用
    vue10行代码实现上拉翻页加载更多数据,纯手写js实现下拉刷新上拉翻页不引用任何第三方插件
    js判断手机或Pc端登陆.并跳转到相应的页面
    移动端touch事件封装
    坦然面对:应对前端疲劳
    webpack2 项目
    PPK提供的浏览器类型及版本检测方法
    2013年五大主流浏览器 HTML5 和 CSS3 兼容性大比拼
  • 原文地址:https://www.cnblogs.com/superhedantou/p/5936460.html
Copyright © 2020-2023  润新知