“有人把我一個分區(qū)表的某個分區(qū)數據文件刪掉了名惩,這個能查出來么?”
“具體什么情況钮追?”
“我有一個表存了近兩年的數據预厌,按天分區(qū),執(zhí)行show partition 可以看到20171130這個分區(qū)元媚,但是在hdfs上卻找不到這個分區(qū)的數據轧叽。”
數倉和元數據系統(tǒng)的同學一起找到我刊棕,向我提出了上面的問題炭晒。看這氣勢是要把誤刪數據的罪魁禍首揪出來祭天的節(jié)奏甥角。
hive元數據信息和數據文件不一致的情況有時候確實會出現网严。如不同用戶操作引起的權限問題,或直接通過MR或spark寫入數據文件等嗤无,但之前遇到的這些情況都是hive元數據中已經刪除震束,而數據文件依然存在。
那么這次真的是人為操作引起的么当犯?
首先要找到這個分區(qū)的數據文件是什么時候刪的垢村。我們的元數據系統(tǒng)每天會對有更新的表執(zhí)行count 計算,當分區(qū)的數據文件找不到時嚎卫,count 就會報錯嘉栓,所以根據日志中開始報錯的日期,時間是2018-09-28驰凛。
那么這些分區(qū)是什么時候建的呢胸懈?根據hdfs中的其他分區(qū)文件的修改日期,可以看到同樣是2018-09-28恰响。當天數倉同學一共刷了近兩年的分區(qū),看了一下涌献,唯獨少了20170830分區(qū)的文件胚宦,而且就在同一天,執(zhí)行count運算已經報錯了燕垃。所以真的是有人在分區(qū)創(chuàng)建出來的當天正好操作hdfs并誤刪了這些文件枢劝?還是說就是刷數據的時候出錯了呢?當天操作的同學確定當時刷數據是沒有報錯的卜壕,所以可能是hive的bug引起的靜默錯誤您旁。
查看hiveserver 2018-09-28 當天的日志尋找線索,根據表名以及分區(qū)關鍵字查找轴捎,果然有異常鹤盒。對比分析20170830和20170829兩個分區(qū)的日志蚕脏,可以看到20170829這個分區(qū)的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這個分區(qū)的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分區(qū)?
2.20170830這個分區(qū)的load過程中,Thread-529751 為什么會有Moved to trash這樣的行為侦锯?
對于第一個問題驼鞭,hive driver 中處理一個query請求,只會有一個線程負責compile尺碰、submit job挣棕、commit等操作,所以可能是操作的同學當時重復提交了請求亲桥。由于已經是兩周之前的操作了洛心,他也無法確定當時是否重復提交,不過當時確實有開4個dp頁面同時刷不同分區(qū)的情況题篷。查看當天的日志皂甘,兩年的數據只有那半年的分區(qū)是有兩個線程同時在處理的。而當時他確實是以每半年的數據為一個刷數據的請求進行操作的悼凑。所以基本上就是那個請求提交了兩次偿枕。
對于第二個問題,根據日志中的一些關鍵字户辫,定位到load partition的函數為HiveMetaStore.HMSHandler.add_partition_core渐夸,其中l(wèi)oad partition的邏輯簡化后如下:
- 檢查分區(qū)是否已存在
- 若分區(qū)目錄不存在,創(chuàng)建分區(qū)目錄
- 嘗試向metastore寫入新分區(qū)的信息
- 如果第3步寫入失敗并且第二步創(chuàng)建了目錄渔欢,把該目錄刪除墓塌。
結合日志,可以看出線程Thread-529751 執(zhí)行到了第2步之后被掛起奥额,然后線程Thread-529691 執(zhí)行完所有步驟苫幢,load分區(qū)成功。接著Thread-529751 被喚醒垫挨,第4步刪除了分區(qū)文件韩肝。
解決方案:
可以在第4步重新檢查分區(qū)是否已存在,若已存在則不刪除該目錄九榔。Fix 的代碼可見 HIVE-20725