You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL 11升级至12时abstime函数权限授予失败的问题求助

解决PostgreSQL 11→12升级中abstime函数权限报错的问题

这是典型的PostgreSQL版本迭代带来的兼容性问题——PostgreSQL 12彻底移除了abstime、reltime、tinterval这类遗留时间类型,以及对应的所有系统函数。你旧集群里针对这些函数的GRANT语句,在新集群里找不到对应的对象,自然就会触发pg_restore报错。同时系统表pg_shadow和pg_user的valuntil列,在PG12中已经从abstime改为timestamptz,不过这部分pg_upgrade通常会自动处理,重点还是权限的清理。

具体解决步骤

1. 清理旧PG11集群中的无效权限

这些pg_catalog下的abstime相关函数都是系统内置对象,普通用户(比如你的admin)根本不需要手动授予权限——系统默认的权限配置已经足够。所以第一步要在旧集群里撤销这些多余的授权:

首先连接到你的PG11集群:

psql -U postgres -d your_database_name

先确认这些权限确实存在(可选,但建议做):

SELECT routine_name, privilege_type 
FROM information_schema.role_routine_grants
WHERE specific_schema = 'pg_catalog' 
  AND routine_name LIKE '%abstime%' 
  AND grantee = 'admin';

然后执行批量撤销操作(对应你导出的所有GRANT语句,改成REVOKE即可):

REVOKE ALL ON FUNCTION pg_catalog.abstime(timestamp without time zone) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstime(timestamp with time zone) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstimeeq(abstime, abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstimege(abstime, abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstimegt(abstime, abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstimein(cstring) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstimele(abstime, abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstimelt(abstime, abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstimene(abstime, abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstimeout(abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstimerecv(internal) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.abstimesend(abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.btabstimecmp(abstime, abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.date(abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.date_part(text, abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.intinterval(abstime, tinterval) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.isfinite(abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.mktinterval(abstime, abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog."time"(abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.timemi(abstime, reltime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.timepl(abstime, reltime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog."timestamp"(abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.timestamptz(abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.tinterval(abstime, abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.max(abstime) FROM admin;
REVOKE ALL ON FUNCTION pg_catalog.min(abstime) FROM admin;

完成后,重新运行pg_upgrade的预检查,再执行实际升级操作,应该就能绕过权限报错了。

2. 关于pg_shadow/pg_user的valuntil列

PostgreSQL 12已经将这两个系统表的valuntil列类型从abstime改为timestamptz,不过abstime本质上是timestamp without time zone的别名,pg_upgrade在升级过程中会自动完成类型转换,不需要你手动干预。如果不放心,可以在旧集群里先检查一下这列的数据:

SELECT usename, valuntil FROM pg_shadow WHERE valuntil IS NOT NULL;

只要数据是有效的时间值,转换过程不会有问题。

3. 备选方案:用逻辑备份跳过无效权限

如果因为某些原因无法修改旧集群(比如只读环境),可以改用逻辑备份(pg_dump)的方式迁移:

  • 先备份旧集群:
    pg_dump -U postgres -d your_database_name -f pg11_backup.sql
    
  • 手动编辑备份文件,删除所有包含abstime的GRANT语句;
  • 在PG12集群中恢复备份:
    psql -U postgres -d your_database_name -f pg11_backup.sql
    

4. 升级后的验证

完成升级后,建议连接到PG12集群做两个检查:

-- 确认admin用户没有无效的权限条目
SELECT * FROM information_schema.role_routine_grants WHERE grantee = 'admin';

-- 确认valuntil列类型已经转换为timestamptz
SELECT column_name, data_type 
FROM information_schema.columns 
WHERE table_name = 'pg_shadow' AND column_name = 'valuntil';

内容的提问来源于stack exchange,提问作者Michał Zawistowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 03:12:32