单节点内部元数据不一致类问题
问题描述
单个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有延迟,则需要排查解决同步延迟问题。