單節點內部元數據不一致類問題
問題描述
單個CN或DN主節點內部元數據不一致問題,對應pg_check()元數據檢查返回類型“inter_check”,例如:pg_class.relhasindex標識該表是否有索引,如果和索引不一致,則會檢測出來;有表,但是pg_attribute中沒有表記錄。
例如,以下select * from pg_check(); 查詢結果:
產生元數據不一致的主要原因:在元數據缺失的節點上,主節點和備節點不同步,DDL語句在備節點未應用時,發起了主備切換,備升主后,該備節點元數據與其它主節點不一致。
可能影響
- 索引不準確,可能會導致執行計劃生成不準;
- 元數據不一致,可能會導致對象訪問出錯,例如表缺少字段,訪問表時會出錯。
解決步驟
- 元數據不一致檢查及分析
首先根據select * from pg_check();結果梳理和分析元數據不一致情況,第一列check_type=inter_check,表示為節點內存部元數據不一致,然后根據查詢結果再進一步分析,常見的情況:
1)pg_class.relhasindex與表的實際索引情況不一致,例如上面查詢結果,cn001節點pg_class.relhasindex和pg_index的元數據不一致。
檢查辦法:
a、根據檢查結果,拼出SQL如下,得到test_varchar2表索引test_varhcar2_id_idex;
teledb=# select indexrelid::regclass,indrelid::regclass from pg_index where indexrelid=34461;
indexrelid | indrelid
----------------------+---------------
test_varchar2_id_idx | test_varchar2
(1 row)
b、拼出SQL如下,得到pg_class.relhasindex=f,表示該表上沒有索引;
teledb=# select relname,relhasindex from pg_class where oid=34458;
relname | relhasindex
---------------+-------------
test_varchar2 | f
(1 row)
2)pg_class.relnatts與表/索引的實際字段不一致,例如下面截圖是索引test_varchar2_id_idx實際字段和pg_class.relnatts記錄不一致的問題:

檢查辦法:
a、根據檢查結果,拼出SQL如下,得到pg_class記錄索引test_varhcar2_id_idex有1個字段;
teledb=# select relname,relnatts from pg_class where oid=34461;
relname | relnatts
----------------------+----------
test_varchar2_id_idx | 1
(1 row)
b、根據檢查結果,拼出SQL如下,得到pg_attribute沒有索引test_varhcar2_id_idex的記錄,即count(attrelid)=0;
teledb=# select count(attrelid) from pg_attribute where attrelid=34461;
count
-------
0
(1 row)
- 解決辦法:
1)pg_class.relhasindex與表的實際索引情況不一致:
解決辦法:更新pg_class.relhasindex,如:
update pg_class set relhasindex=true where relname='test_varchar2';
2)pg_class.relnatts與表/索引的實際字段不一致:
解決辦法:缺失字段,通常需要手動補全記錄,可從其它有完整字段的節點上導出記錄。修改attrelid值(每個節點創建對象時生成的oid值不同),然后導入缺少的節點中。
注意元數據一致問題修復需要操作CN節點、DN節點,應在TeleDB運維專家/開發人員的指導下進行,避免因操作失誤造成更大損失。
主節點之間元數據不一致問題問題
問題描述
所有個CN、DN主節點之間元數據不一致問題,對應pg_check()元數據檢查返回類型“cross_check”,例如,某個對象,如庫、模式、表、索引、字段等,在其中1個或多個CN、DN主節點上不存在。
例如,以下select * from pg_check(); 查詢結果:
產生元數據不一致的主要原因:在元數據缺失的節點上,主節點和備節點不同步,DDL語句在備節點未應用時,發起了主備切換,備升主后,該備節點元數據與其它主節點不一致。
可能影響
- 對于應存在,但某些節點實際缺失的情況,訪問到該對象的語句會報錯;例如上圖元數據問題,查詢表時會有如下報錯:
teledb=# select count(*) from test_varchar2;
ERROR: ?node:dn002, backend_pid:25375, nodename,backend_pid,message:dn002,25375,could
not open relation with OID 0
- 對于應不存在,但某些節點實際存在的情況,造成無用對象殘留,空間被占用(如DN上大表殘留)。
解決步驟
- 元數據不一致檢查及分析
首先根據select * from pg_check();結果梳理和分析元數據不一致情況,第一列check_type=cross_check,最后一列isfound=true表示該節點上有此對象,isfound=false表示無此對象,根據各CN、DN節點的isfound結果分析,對象應存在,還是應不存在。通常情況:
1)對象不存在的場景,某個節點上isfound=true,其它所有節點上isfound=false;
2)對象應存在的場景,某個節點上isfound=false,其它所有節點上isfound=true;
3)初步判斷后,或無法區分時,應與業務側進行核實確認;
- 制定修復方案:
1)對象應不存在的場景,修復起來相對簡單,梳理出缺失的對象,然后執行drop if exists xxx;命令刪除,需要增加if exists關鍵字,在缺失對象的節點上不會報錯;
通常是表缺失,同時基于表的索引、類型、字段等缺失。例如上述截圖中,可以判斷出dn002節點上缺失了test_varchar2表。這里我們如果要修復,執行 drop if exists test_varchar2;語句就可以了;
a、所有CN主節點上沒有該對象,需要連接所有DN主節點,開啟事務寫,drop該對象;
b、部分CN主節點上沒有該對象,需要連接有該對象的主CN,執行drop if exists test_varchar2;
c、部分DN主節點上沒有該對象,需要連接有該對象的主CN,執行drop if exists test_varchar2;
2)對象應存在的場景,要在節點上補缺失的對象,需要判斷缺失對象的節點類型
a、CN節點上需要補缺失的對象,需要單用戶模式啟動該CN主節點,創建對象;
b、DN節點上需要補缺失的對象,需要連接該DN主節點,開啟事務寫,創建對象;
注意元數據一致問題修復需要操作CN節點、DN節點,應在TeleDB運維專家/開發人員的指導下進行,避免因操作失誤造成更大損失。
主備節點之間元數據不一致問題
問題描述
同一組CN、DN的主備節點之間元數據不同步,可以理解為在主節點上執行的DDL語句,還沒有同步到備節點,或者WAL日志已同步但未應用。
注意:該問題通過pg_check()無法檢測,pg_check()只檢測主節點內部、主節點之間元數據一致性;但主備節點之間元數據不一致出現后,再發生主備切換,就會導致節點之間的元數據不一致。
可能影響
- 只讀平面的數據因延遲較大而不準確;主節點異常后,可能有丟失數據的風險;
- 異步復制狀態下,如果手動發起切換,可能造成元數據不一致,數據丟失風險;
特別提醒:應定期檢查主備節點同步情況,不應有主備同步復制斷連、同步延遲過大的問題。
解決步驟
- 定期巡檢,檢查主備節點同步延遲情況;可執行以下SQL:
select current_setting('synchronous_standby_names') as
synchronous_standby_names,client_addr,application_name,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)/1024/1024 as diff,sync_state from
pg_stat_replication;
- 如果備節點未連接、或連接異常,先解決備節點異常問題;
- 如果備節點與主節點之間復制狀態正常,只是同步或應用WAL有延遲,則需要排查解決同步延遲問題。