记录一个openguass(mogdb)checkpoint不推进的问题(续)

前几天我在《记录一个OpenGauss(MogDB) checkpoint不推进的问题》中描述了一个现象,最近几天也一直在尝试解决。由于我对OpenGauss还算不上专家,因此在处理过程中积累了一些实践心得,包括使用VACUUM FULLpg_repack对表进行重组,以及如何检查relfilenode所属对象并判断其是否为孤儿文件。这里简单做个记录。

错误日志

Note: 错误日志中主要是page nnn of relation pg_tblspc/xxx/xxx/xxx18066xxx/2144519xx does not exist的格式。

处理路线

通过日志中的数据过滤,我基本确定了几个relfilenode对应的对象,均为业务高峰期频繁操作的表。推测问题可能是在业务维护过程中执行表DDL时,业务并未完全停止,进而导致了这一现象。

在问题处理中,我尝试了使用VACUUM FULLpg_repack对表进行在线重组。

  • VACUUM FULL操作需要获取排它锁,并且需要约两倍于原表的空间。若业务负载较高,建议在业务低峰期或暂停时段执行。此外,该操作支持针对表的分区级别进行,可有效减少对总空间的需求。
  • pg_repack要求目标表具备主键(primary key)或非空唯一索引(non‑null unique index),即等效于主键约束。

关于relfilenode未出现在pg_class.relfilenode中的情况,这与OpenGauss(源于PostgreSQL)的分区机制有关:部分分区信息记录在pg_partition中,而非全部位于pg_class。因此,这些并非最初猜测的孤儿文件(Orphaned files)。实际排查时,可通过filenode结合pg_classpg_partition系统表来定位其所属对象。

SELECT 
    pg_class.oid,
    pg_class.relname,
    pg_namespace.nspname as schema_name,
    pg_class.relfilenode,
    pg_class.relkind,
    CASE pg_class.relkind
        WHEN 'r' THEN '普通表'
        WHEN 'i' THEN '索引'
        WHEN 'S' THEN '序列'
        WHEN 't' THEN 'TOAST表'
        WHEN 'v' THEN '视图'
        WHEN 'm' THEN '物化视图'
        WHEN 'c' THEN '复合类型'
        WHEN 'f' THEN '外部表'
        WHEN 'p' THEN '分区表'
        WHEN 'I' THEN '分区索引'
    END as object_type
FROM pg_class
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
WHERE pg_class.relfilenode = 63402       ---------------- modify 
union all
select 
    p.oid,
    p.relname||'.'||s.relname ,
    ns.nspname as schema_name,
    s.relfilenode,
    p.relkind,
CASE s.parttype
        WHEN 'r' THEN '分区表'
        WHEN 'p' THEN '表分区'
        WHEN 'x' THEN '索引分区'
        WHEN 't' THEN 'TOAST表分区'
    END as part_type
FROM pg_class p
join PG_PARTITION s on p.oid=s.parentid 
LEFT JOIN pg_namespace ns ON p.relnamespace = ns.oid
where  s.relfilenode=63402        ---------------- modify 

最后找停机窗口,对表做vacuum full 修复报错refilenode的表及分区,再重建备库。