元数据回滚后读ao/orc表报错 Failed to open layout file xxxx

问题背景

在一个客户环境下,升级时做了元数据导入导出,但在运行几天之后,又重新回滚了所有元数据,此时读一些 ao/orc 表,得到报错 ERROR: Failed to open layout file xxx,例如:

问题排查

以上述问题为例:

  1. 先查出这张表的 oid select oid from pg_class where relfilenode = 36059;
  2. 再查看这张表的 aoxr select * from oushu_aoxr(36059) t (rootrelid oid, relfilenode oid, state int2, version int8);
  3. 再对比这张表的实际数据文件:hdfs dfs -ls /oushudb/default_filespace/16385/16655/36059

NOTE(关于 AOXR):aoxr 是一张元数据表,记录了相应用户表路径下有哪些子文件夹,各字段表示:

  1. rootrelid 和 relfilenode 字段是和 pg_class 中相应字段相同,一般没有问题
  2. state 记录了子文件夹的前缀,version 记录了子文件夹的后缀

举几个例子:

  1. state = 1, version = xxx, 表示有一个子文件夹:d_xxx
  2. state = 2, version = xxx, 表示有一个子文件夹:i_xxx
  3. state = 3, version = xxx, 表示有两个子文件夹:i_xxx 和 d_xxx
  4. state = 6, version = xxx, 表示有一个子文件:bi_xxx

具体的转换逻辑参考代码 oushudb/src/backend/access/appendonly/aoxr.c:84 函数 GetTransactionDirPrefix

问题分析

从上述结果可以看到,db 是按照 aoxr 里的记录读取数据文件的,但这张表的 aoxr 记录和它的实际物理文件不匹配,所以读的时候会报错:找不到 layout 文件。

这个场景产生的原因是,db 在元数据回滚前的那几天触发了 auto compact,更新了 aoxr,这样元数据回滚之后,就有问题。

从 db 那几天的日志应该可以找到 compact 记录,不凑巧客户环境的日志丢失了,但可以看到 hdfs 文件夹的日期恰好是元数据回滚前的那天,从而印证上述的分析。

问题修复

修复手段就是把 aoxr 搞成和 hdfs 物理文件一致,在上述例子中,就是要把 aoxr 的记录全部删除,然后插入 (36059, 36059, 6, 122031176),所以执行的 SQL 为

drop function if exists insert_oushu_aoxr(oid, oid, int2, int8);
create function insert_oushu_aoxr(oid, oid, int2, int8) returns void as '$libdir/hornet', 'insert_oushu_aoxr' language c volatile;

drop function if exists delete_oushu_aoxr(oid, oid, int2, int8);
create function delete_oushu_aoxr(oid, oid, int2, int8) returns void as '$libdir/hornet', 'delete_oushu_aoxr' language c volatile;

-- 用 delete_oushu_aoxr 依次删除每一行

select delete_oushu_aoxr('36059'::oid, '36059'::oid, '6'::int2, '117695917'::int8);

...

-- 用 insert_oushu_aoxr 依次插入每一行

select insert_oushu_aoxr('36059'::oid, '36059'::oid, '6'::int2, '122031176'::int8);

...

-- 此时表应该能正常读取

select '36059'::regclass;

select count(*) from ${table_name};

问题延伸

目前没有好的办法确定:整个数据库中有哪些表的 aoxr 是不一致需要修复的。实际上,如果 db 相关日志还在的话,过滤 compact 记录很容易就能找到,但现在好像只能客户遇到一张问题表就修一次。(可能通过 hdfs -ls 再筛选日期也能大致得到有问题的表,不确定实际可行性)

评论
  • 回复

    👍🏻👍🏻👍🏻

test