大數據“復活”記
1852
2025-03-31
前言
元數據不一致問題往往會導致業務上的報錯,在現網環境中,“元數據不一致”一詞常常讓客戶、一線、二線甚至研發兄弟們談虎色變,但是很多人其實并不清楚“元數據不一致”到底是什么,該如何處理。元數據不一致真的有那么可怕嗎?接下來本文將以一種常見的元數據不一致場景為例,帶領讀者揭開元數據不一致的神秘面紗
聲明
1.此系列博文的初衷是構建更加強大的生態社區,提升大家對GaussDB(DWS)的認識,在現網運維過程中減少工具人的角色,因此只講解元數據不一致的原理和應急方法,不討論“是否為產品質量問題”等敏感話題
2.此系列博文所有數據內容均為實驗環境構造,非客戶數據,不涉及客戶隱私
3.此系列屬于技術原理類博文,不建議客戶、一線、二線在讀完此系列之后直接處理生產環境的元數據不一致問題
什么是元數據不一致
在執行DDL操作時,會將表的元信息記錄在系統表中,例如,執行一個簡單的create table test(a int,b int)操作,會在pg_class中新增一條數據來記錄表信息,在pg_type中新增一條數據來記錄與這張表對應的存儲數據類型,在pg_depend中新增一條數據來記錄pg_class中的數據和pg_type中的數據之間的依賴關系,在pg_attribute中新增九條數據來記錄字段a、字段b以及表的7個默認隱藏字段。
當系統表之間的信息不匹配時,就出現了元數據不一致的場景,例如,當pg_class中記錄還在,而pg_attribute中對應記錄不存在時,訪問該表就會報錯。
常見的系統表之間依賴關系如下圖
一種經典問題場景
元數據不一致的場景有很多,這里我們先看一種比較經典的場景:Catalog is missing n attribute(s) for relid xxx
(這里在測試環境上已經構造好了問題場景,構造方法會附在博文最后)
測試環境:3節點,每個節點1個cn,4個主dn
集群拓撲:
問題現象:在cn5001上查詢select * from public.testmissingattr時報錯:dn_6001_6002: Catalog is missing 2 attribute(s) for relid 62439689
問題分析:
1.首先分析報錯信息,Catalog is missing n attribute(s) for relid xxx的直接報錯原因,是pg_class中該表的relnatts字段與pg_attribute中該表非隱藏列的記錄數不匹配
pg_attribute中attnum大于0的記錄表示非隱藏列
2.根據報錯信息中的detail,我們可以確定在dn6001上,pg_class中該表的relnatts字段值為4,而pg_attribute中缺少了attnum為1和3的字段記錄;該表在dn6001上pg_class中的oid為62439689
3.到dn6001上確認問題現象(如何連接某個dn不在此贅述)
select oid,* from pg_class where oid = 62439689;
可以看到在pg_class中relnatts的值確實是4
select * from pg_attribute where attrelid = 62439689;
可以看到pg_attribute中確實缺少了attnum為1和3的列
注意,當發生元數據不一致時,一定要先判斷不一致時到底哪一側是正確的,在此場景中就是要判斷是pg_class中的relnatts值記錄錯誤,還是pg_attribute中記錄缺失
判斷的依據,往往是根據cn或其他正常未報錯的dn來判斷,或從業務側進行判斷
(由于pg_attribute中一張表的attnum一定是連續的,因此根據上圖可以快速判斷是pg_attribute中缺少記錄,但是如果上圖存在的兩條記錄attnum為1,2而不是2,4,就要根據其他cn或dn的表定義來進行判斷)
在cn查看表定義,確認是4個字段,pg_class中記錄正確,pg_attribute中缺失字段a和c
3.由于系統表的查詢都是優先從syscache中掃描,而syscache都是帶索引掃描,因此我們需要將索引關掉,再查詢一遍,來確認是僅有索引中缺少這兩條記錄,還是pg_attribute中確實缺少這兩條記錄。
關閉索引再次查詢:
start transaction read only;
set enable_indexscan=off;
set enable_bitmapscan=off;
explain select * from pg_attribute where attrelid = 62439689;
確認執行計劃是走seq scan之后,再次查詢
select * from pg_attribute where attrelid = 62439689;
rollback;
再次查詢的結果,可以分為兩種情況討論:
關閉索引后,查詢正常
這說明數據本身沒有缺失,只是索引文件中缺失了,因此只要重建索引即可修復
在dn上對系統表重建索引:
start transaction read write;
reindex table pg_attribute;
commit;
需要注意的是,在cn上不能直接對系統表重建索引,會報錯cannot PREPARE a transaction that modified relation mapping,因此如果是cn上需要重建系統表的索引,就要對系統表做vacuum full進行修復
vacuum full pg_attribute;
關閉索引后,查詢結果不變
這說明是pg_attribute中確實缺少了記錄,此時我們優先查到對應的備dn(在此案例中為6002)是否正常,如果備dn正常,則停止集群,從備dn拷貝對應文件到主dn
如何找到表的對應文件,不在這里贅述,可參考博文:GaussDB(DWS)磁盤使用率相關問題定位指南https://bbs.huaweicloud.com/blogs/174806
如果備dn與主dn查詢結果一致,則需要手動恢復一致性,此場景一般根據正常cn或dn的pg_attribute記錄,將缺失的記錄在dn6001補齊
恢復步驟:
a.在正常的cn或dn查詢該表在pg_attribute中attnum為1和3的字段
在cn5001執行:
select oid,* from pg_class where relname = 'testmissingattr' and relnamespace = (select oid from pg_namespace where nspname = 'public'); #同一張表在不同的cn和dn上oid都是不一樣的,要重新查詢
select * from pg_attribute where attrelid = 574785;
查到缺失的兩條記錄,根據此信息在dn6001上補齊
在dn6001執行
start transaction read write;
insert into pg_attribute values (62439689,'a',23,-1,4,1,0,-1,-1,'t','p','i','f','f','f','t',127,0,0,NULL,NULL,NULL,NULL);
insert into pg_attribute values (62439689,'c',23,-1,4,3,0,-1,-1,'t','p','i','f','f','f','t',127,0,0,NULL,NULL,NULL,NULL);
select * from pg_attribute where attrelid = 62439689;
確認已經補齊
select * from public.testmissingattr limit 1;
查詢該表不再報錯
commit;
提交事務使修復生效
到這里,此場景已經修復完畢,表可以繼續正常使用
注意事項:
所有操作都放在事務中做,執行結果不符合預期之后及時回滾
找對cn/dn
系統表字段不要混淆
總結
本文以一個經典的元數據不一致場景為例,介紹了元數據不一致的原理、定位及修復,下期博文將繼續介紹元數據不一致的其他經典場景,幫助大家更好的理解元數據不一致現象
附:場景構造
在cn執行
create table public.testmissingattr(a int,b int,c int,d int);
在任一dn執行
start transaction read write;
delete from pg_attribute where attrelid = (select oid from pg_class where relname = 'testmissingattr' and relnamespace = (select oid from pg_namespace where nspname = 'public')) and attname = 'a';
delete from pg_attribute where attrelid = (select oid from pg_class where relname = 'testmissingattr' and relnamespace = (select oid from pg_namespace where nspname = 'public')) and attname = 'c';
commit;
EI企業智能 Gauss AP 數據倉庫服務 GaussDB(DWS)
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。