系统表介绍
常用系统表介绍如下:
名称 |
说明 |
pg_class |
存储数据库中表对象的信息 |
pg_database |
存储系统内数据库对象信息 |
pg_proc |
存储函数或存储过程的信息 |
pg_namespace |
存储schema相关信息 |
pg_authid |
存储用户相关信息 注意:需要有系统管理员权限才可以访问此系统表 |
pg_attribute |
存储关于表字段的信息 |
pg_type |
存储数据类型的相关信息 |
pg_partition |
存储分区表分区相关信息 |
pg_tablespace |
存储表空间相关信息 |
pg_statistic |
存储有关该数据库中表和索引列的统计数据 注意:需要有系统管理员权限才可以访问此系统表 |
pgxc_class |
存储每张表的分部信息 |
系统表关系
其中元数据不一致问题一般涉及6张系统表:
pg_class, pg_attribute, pg_depend, pg_type, pg_index, pg_partition
- 一张新表创建时,会在pg_class, pg_type, pg_depend中各新增一条记录(先不考虑toast、cudesc、delta),同时在pg_attribute中对表的每个字段都新增一条记录;
- 对表新增索引时,会在pg_class, pg_index, pg_depend中各新增一条记录;
- 有分区时,pg_partition中会记录分区信息。
一致性要求
- pg_class和pg_attribute中要求一致,即对于pg_class中的一条记录(即一张表),每一个字段都要在pg_attribute中有一条对应记录;当pg_attribute中该表的记录缺失时,就会出现类似“Catalog is missing 2 attribute(s) for relid 8322560”这种报错;
一般情况下pg_attribute中不会多出来记录,只遇到过一次,pg_attribute系统表本身触发了btree分裂的bug,导致按索引查询时,每一个tuple在索引中都有两条记录,可以通过查ctid确定索引查出来的两条记录是否为同一个tuple;此场景只需对pg_attribute做reindex即可;
对dn的系统表做写事务时,需要注意,不要用-m模式,也不要从cn下发,而是在dn开启一个read write事务做reindex;
这里顺便强调一点,在处理元数据不一致的问题时,都要考虑是系统表本身tuple有问题,还是系统表的索引有问题导致查出来不一致;在大部分内部逻辑中,都是使用syscache,syscache都是走索引的。 - pg_class、pg_type、pg_depend要求一致;对于一张业务表,在pg_class和pg_type中各有一条记录,同时通过pg_depend来记录依赖关系;
当pg_class和pg_depend中记录还在,pg_type中记录丢失时,在做drop table等操作时就会出现类似“cache lookup failed for type 8323668”的报错;
当pg_class中记录不存在,但是pg_type中记录仍存在时,创建一张同名的新表时会出现类似“type xxx already exists”的报错。 - pg_class、pg_index、pg_depend要求一致;表和索引都是relation,在pg_class中分别有一条记录,同时在pg_depend中记录依赖关系,在pg_index中记录索引关系;
当pg_index记录缺失时,就会出现类似“cache lookup failed for index 8323033”的报错;
当pg_class中这条索引的记录缺失时,就会出现类似“index xxx does not exist”的报错;
当pg_class中表的记录已删除,索引记录残留时,下次创建同名的表,再创建同名索引时就会出现类似“index xxx already exists”的报错。 - 不同cn、dn之间要求元数据一致。当不同实例之间出现元数据不一致时,先确认在缺失的实例上是完全缺失还是部分缺失,完全缺失就是指pg_class、pg_index、pg_type、pg_depend、pg_attribute中都没有相关记录,部分缺失就是指一部分系统表中有此记录。
对于部分缺失,按照前三种场景在单dn上处理之后,再处理dn之间的不一致;
对于完全缺失,在缺失的dn上将该表或索引重新创建出来即可。 - schema要求一致。对于“xxx does not exist”的报错,考虑是否为语句中未指定schema导致,此场景为非问题;
之前还遇到过不同实例上,schema错乱的问题,可以联合pg_class和pg_namespace进行确认。 - 唯一索引不能违背唯一性。当出现类似“duplicate key value violates unique constraint”的报错时,说明违背了唯一索引的唯一性,需根据报错信息中具体的索引信息,检查是否有违背唯一性的记录;
当出现此报错,但是使用语句“select indextblid,count(*) from pg_partition group by 1 having count(*) > 1”查不到记录时,需注意,此语句使用了group by,不会走索引,要考虑是否是系统表的索引出了问题,需要reindex重建。