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就沒問題了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM