hive迷案之消失的分割槽檔案

youou發表於2021-09-09

“有人把我一個分割槽表的某個分割槽資料檔案刪掉了,這個能查出來麼?”
“具體什麼情況?”
“我有一個表存了近兩年的資料,按天分割槽,執行show partition 可以看到20171130這個分割槽,但是在hdfs上卻找不到這個分割槽的資料。”
數倉和後設資料系統的同學一起找到我,向我提出了上面的問題。看這氣勢是要把誤刪資料的罪魁禍首揪出來祭天的節奏。
hive後設資料資訊和資料檔案不一致的情況有時候確實會出現。如不同使用者操作引起的許可權問題,或直接透過MR或spark寫入資料檔案等,但之前遇到的這些情況都是hive後設資料中已經刪除,而資料檔案依然存在。
那麼這次真的是人為操作引起的麼?

首先要找到這個分割槽的資料檔案是什麼時候刪的。我們的後設資料系統每天會對有更新的表執行count 計算,當分割槽的資料檔案找不到時,count 就會報錯,所以根據日誌中開始報錯的日期,時間是2018-09-28。

那麼這些分割槽是什麼時候建的呢?根據hdfs中的其他分割槽檔案的修改日期,可以看到同樣是2018-09-28。當天數倉同學一共刷了近兩年的分割槽,看了一下,唯獨少了20170830分割槽的檔案,而且就在同一天,執行count運算已經報錯了。所以真的是有人在分割槽建立出來的當天正好操作hdfs並誤刪了這些檔案?還是說就是刷資料的時候出錯了呢?當天操作的同學確定當時刷資料是沒有報錯的,所以可能是hive的bug引起的靜默錯誤。

檢視hiveserver 2018-09-28 當天的日誌尋找線索,根據表名以及分割槽關鍵字查詢,果然有異常。對比分析20170830和20170829兩個分割槽的日誌,可以看到20170829這個分割槽的load過程(也就是正常情況):

Thread-529691:Creating directory if it doesn't exist
Thread-529691:add_partition
Thread-529691:New loading path

Thread-529751:Creating directory if it doesn't exist
Thread-529751:alter_partition
Thread-529751:New loading path

而20170830這個分割槽的load過程:

Thread-529751:Creating directory if it doesn't exist

Thread-529691:Creating directory if it doesn't exist

Thread-529751:add_partition

Thread-529691:add_partition
Thread-529691:New loading path

Thread-529751:Moved to trash
Thread-529751:error using statement "INSERT INTO PARTITIONS ... " failed : Duplicate entry
Thread-529751:add_partition
Thread-529751:AlreadyExistsException
Thread-529751:alter_partition
Thread-529751:New loading path

這裡有兩個問題

1.為什麼有兩個執行緒在load分割槽?
2.20170830這個分割槽的load過程中,Thread-529751 為什麼會有Moved to trash這樣的行為?

對於第一個問題,hive driver 中處理一個query請求,只會有一個執行緒負責compile、submit job、commit等操作,所以可能是操作的同學當時重複提交了請求。由於已經是兩週之前的操作了,他也無法確定當時是否重複提交,不過當時確實有開4個dp頁面同時刷不同分割槽的情況。檢視當天的日誌,兩年的資料只有那半年的分割槽是有兩個執行緒同時在處理的。而當時他確實是以每半年的資料為一個刷資料的請求進行操作的。所以基本上就是那個請求提交了兩次。

對於第二個問題,根據日誌中的一些關鍵字,定位到load partition的函式為HiveMetaStore.HMSHandler.add_partition_core,其中load partition的邏輯簡化後如下:

  1. 檢查分割槽是否已存在

  2. 若分割槽目錄不存在,建立分割槽目錄

  3. 嘗試向metastore寫入新分割槽的資訊

  4. 如果第3步寫入失敗並且第二步建立了目錄,把該目錄刪除。

結合日誌,可以看出執行緒Thread-529751 執行到了第2步之後被掛起,然後執行緒Thread-529691 執行完所有步驟,load分割槽成功。接著Thread-529751 被喚醒,第4步刪除了分割槽檔案。



作者:群演_
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4729/viewspace-2817370/,如需轉載,請註明出處,否則將追究法律責任。

相關文章