PG 9.4枚举类型权限显示OID无法删除,恢复失败求助
PostgreSQL 9.4枚举类型无效权限问题的分析与解决
是否属于Bug?
这是PostgreSQL 9.4及更早版本的已知问题:当角色被删除后,系统不会自动清理该角色关联的所有权限条目,导致权限列表中出现以角色OID(此处的16524即为已删除角色的OID)显示的无效权限项。该问题在PostgreSQL 9.5及后续版本中已被修复,新版本会在删除角色时同步清理所有关联权限。
不升级数据库的解决办法
方法1:直接修改系统目录(高危操作,需先备份)
PostgreSQL的权限信息存储在系统表中,枚举类型的权限对应pg_type表的typlacl字段,可通过以下步骤清理无效权限:
- 开启允许修改系统表的模式:
SET allow_system_table_mods = true;
- 查询目标枚举类型的当前权限,确认要移除的条目:
SELECT typlacl FROM pg_type WHERE typname = 'gender' AND typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'myschema');
- 移除包含
16524的权限项:
UPDATE pg_type SET typlacl = ARRAY_REMOVE(typlacl, '=U/16524'::aclitem) WHERE typname = 'gender' AND typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'myschema');
- 关闭系统表修改模式:
SET allow_system_table_mods = false;
警告:直接修改系统表存在风险,操作前必须备份数据库,且建议在业务低峰期执行。
方法2:通过权限覆盖清理无效条目
若不想修改系统表,可尝试通过赋予再撤销权限的方式覆盖无效条目:
- 先给PUBLIC赋予枚举类型的USAGE权限:
GRANT USAGE ON TYPE myschema.gender TO PUBLIC;
- 再撤销PUBLIC的所有权限:
REVOKE ALL ON TYPE myschema.gender FROM PUBLIC;
重复执行上述步骤,新的权限条目会替换掉原有的无效项,最终完成清理。
方法3:备份时跳过权限语句规避恢复报错
如果仅需解决恢复时的报错,可在备份时使用--no-acl参数,让备份文件不包含权限相关语句:
pg_dump -d 你的数据库名 --no-acl -f backup.sql
恢复该备份文件时不会触发角色不存在的错误,但需注意:此方式会丢失所有自定义权限配置,恢复后需重新设置权限。
内容的提问来源于stack exchange,提问作者Peter Steinheuser
相关产品推荐
相关产品推荐

