找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

5917

积分

0

好友

751

主题
发表于 昨天 14:56 | 查看: 8| 回复: 0

在 PostgreSQL 的日常运维中,pg_dump 逻辑备份偶尔会报出 schema with OID xxx does not exist 这类错误。这类问题看似离奇,其实往往和事务隔离机制下的“孤儿对象”残留有关。云栈社区里也有不少 DBA 讨论过类似场景,今天就把这个坑完整梳理一遍。

适用范围:PostgreSQL 19 以前的版本

问题概述

Session 1:在事务中删除 myschema,未提交

create database mydb;
\c mydb
create schema myschema;
begin;
drop schema myschema cascade;
BEGIN
  │
  ├── DROP SCHEMA myschema CASCADE
  │
  │   当前事务看到:
  │
  │   myschema  → 已删除
  │
  ▼
  未 COMMIT

Session 2:可以创建 myschema.f1 成功

CREATE FUNCTION myschema.f1() 
returns void as $$
begin NULL; end;
$$ language plpgsql;

Session 1 事务提交后,pg_proc 系统表将残留 myschema.f1 的元数据记录。后续对该库做逻辑备份时,pg_dump 就会抛出:

error:schema with OID xxx does not exist

问题原因

这个问题的关键在于:DROP SCHEMA … CASCADE 在 Session 1 中虽然已经执行,但事务还没有提交。

Session 2 创建函数时,获取到的系统快照是一个“事务隔离后的数据库对象视图”。因为 Session 1 的 DROP SCHEMA 尚未提交,Session 2 仍然可以看到 myschema 的旧版本。

也就是说:Session 1 认为自己已经把 myschema 删掉了,但这个删除只对 Session 1 自己可见;Session 2 仍然认为 myschema 存在,所以照样可以在里面创建函数。

当 Session 1 提交事务后,myschema 的元数据信息被正式清除,但 pg_proc 系统表中残留的 f1 函数记录却没有对应的 pg_namespace 条目。pg_dump 在遍历函数对象时,按照 pg_proc 去反查命名空间,结果就撞上了 schema with OID xxx does not exist 的错误。

说到底,这是一个典型的并发 DDL 与事务可见性交互导致的元数据不一致问题。

解决方案

该问题在最新的 v19 已经修复。同时 v19 还提供了对 schema 的打包功能,可以对 schema 初始化依赖的对象进行原子操作,参考语法如下:

CREATE SCHEMA myschema
CREATE TABLE t1(id int)
CREATE VIEW v1 AS SELECT 1
CREATE FUNCTION f1() RETURNS int
LANGUAGE sql
AS $$ SELECT 1 $$;

对于还在使用 19 之前版本的环境,规避思路也比较直接:避免在一个未提交事务中执行 DROP SCHEMA … CASCADE 的同时,另一个会话还对该 schema 做对象创建。生产上的 DDL 变更最好串行执行,或者先将相关连接清理干净再动手。

参考文档:

https://www.postgresql.org/docs/19/release.html




上一篇:Win11 十月更新默认开启内存完整性,老旧游戏设备建议主动关闭
下一篇:Oracle 临时表空间组每日一题:以下哪项描述正确?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-9-10 16:01 , Processed in 1.310546 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表