首页
/ Atlas项目在PostgreSQL升级时出现的表检测问题分析

Atlas项目在PostgreSQL升级时出现的表检测问题分析

2025-06-01 16:45:43作者:傅爽业Veleda

问题背景

在使用Atlas进行PostgreSQL数据库版本升级时(特别是从11升级到13或13升级到15版本),Atlas会错误地认为某些已存在的表需要重新创建。这个问题在Google Cloud SQL环境中尤为明显,且与PostgreSQL的OID(对象标识符)机制密切相关。

技术原理分析

PostgreSQL使用OID作为系统内部对象的唯一标识符。在早期版本(如7.2)中,OID是32位整数,由一个集群范围内的计数器分配。在大型或长期运行的数据库中,这个计数器可能会回绕,导致OID重复。虽然新版本文档不再明确提及这一点,但实际行为可能仍然如此。

关键问题在于:OID在不同系统目录表之间并不是全局唯一的。一个OID值可能在pg_class(存储表信息)和pg_proc(存储函数信息)中同时存在,但代表完全不同的对象。

Atlas的检测机制缺陷

Atlas使用以下SQL查询检测现有表:

SELECT
    t3.oid,
    t1.table_schema,
    t1.table_name,
    pg_catalog.obj_description(t3.oid, 'pg_class') AS comment,
    t4.partattrs AS partition_attrs,
    t4.partstrat AS partition_strategy,
    pg_get_expr(t4.partexprs, t4.partrelid) AS partition_exprs
FROM
    INFORMATION_SCHEMA.TABLES AS t1
    JOIN pg_catalog.pg_namespace AS t2 ON t2.nspname = t1.table_schema
    JOIN pg_catalog.pg_class AS t3 ON t3.relnamespace = t2.oid AND t3.relname = t1.table_name
    LEFT JOIN pg_catalog.pg_partitioned_table AS t4 ON t4.partrelid = t3.oid
    LEFT JOIN pg_depend AS t5 ON t5.objid = t3.oid AND t5.deptype = 'e'
WHERE
    t1.table_type = 'BASE TABLE'
    AND NOT COALESCE(t3.relispartition, false)
    AND t1.table_schema IN ('nexus')
    AND t5.objid IS NULL;

问题出在最后对pg_depend的关联条件上:它只检查objid是否匹配,而没有考虑classid。这会导致当表OID与函数OID相同时,查询错误地将有效表排除在外。

具体案例分析

schema_migrations表为例:

  1. 该表实际存在于数据库中,可通过\d命令验证
  2. 其OID为16580
  3. 在pg_proc中同样存在OID为16580的函数word_similarity
  4. 由于Atlas查询没有区分对象类型,错误地将有效表过滤掉了

解决方案建议

修复方案相对简单:在关联pg_depend表时,应增加对classid的条件限制,确保只检查pg_class类型的对象。修改后的查询应类似:

LEFT JOIN pg_depend AS t5 ON t5.objid = t3.oid AND t5.deptype = 'e' AND t5.classid = 'pg_class'::regclass

总结

这个问题揭示了数据库迁移工具在PostgreSQL环境中需要特别注意的一个细节:OID在不同系统目录间的非唯一性。Atlas作为数据库迁移工具,在处理PostgreSQL时需要更加精确地识别对象类型,避免仅依赖OID进行对象匹配。

对于用户而言,如果在PostgreSQL升级过程中遇到Atlas误报表不存在的情况,可以考虑OID冲突的可能性,并检查相关系统目录表确认对象实际存在情况。

登录后查看全文
热门项目推荐

项目优选

收起
openHiTLS-examplesopenHiTLS-examples
本仓将为广大高校开发者提供开源实践和创新开发平台,收集和展示openHiTLS示例代码及创新应用,欢迎大家投稿,让全世界看到您的精巧密码实现设计,也让更多人通过您的优秀成果,理解、喜爱上密码技术。
C
53
468
kernelkernel
deepin linux kernel
C
22
5
nop-entropynop-entropy
Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entropy是它的后端部分,采用java语言实现,可选择集成Spring框架或者Quarkus框架。中小企业可以免费商用
Java
7
0
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
878
517
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
336
1.1 K
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
180
264
cjoycjoy
一个高性能、可扩展、轻量、省心的仓颉Web框架。Rest, 宏路由,Json, 中间件,参数绑定与校验,文件上传下载,MCP......
Cangjie
87
14
CangjieCommunityCangjieCommunity
为仓颉编程语言开发者打造活跃、开放、高质量的社区环境
Markdown
1.08 K
0
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
349
381
cherry-studiocherry-studio
🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端
TypeScript
612
60