应用连接 PostgreSQL 成功,却在建表或访问对象时报 permission denied for schema public。这说明连接数据库与使用 schema 是两层不同的权限,先确认实际连接角色、目标库和 SQL 操作。
不要直接给所有用户授予 CREATE。 PostgreSQL 15 及以后新建数据库的默认权限与早期版本及升级库可能不同,需按当前库的 ACL 判断。

确认当前连接与报错操作
在报错使用的同一连接上查询:
SELECT current_database(), current_user, current_schema();
SHOW search_path;
记录失败 SQL 是 CREATE TABLE、访问表,还是执行迁移。建表需要目标 schema 的 CREATE,访问其中对象需要 schema 的 USAGE,对象本身还可能要求独立权限。
查看 public schema 的所有者和 ACL
在 psql 中运行 \dn+ public,或由具备权限的管理员检查 pg_namespace。同时核对数据库名,避免在另一个库修改了同名 public schema。
历史升级库可能保留较宽松的默认授权。不要凭 PostgreSQL 版本号猜测现有 ACL;实际权限以当前数据库中的对象状态为准。
区分读写角色与迁移角色
若应用只读取已有表,应让对象所有者或有授权能力的管理员授予所需的 schema USAGE,再按需要授予表的 SELECT。执行数据库迁移的角色才可能需要 schema CREATE。
GRANT USAGE ON SCHEMA public TO app_read;
GRANT CREATE ON SCHEMA public TO app_migrate;
这些是示例角色名,执行前先核对角色与安全策略。USAGE 不等于自动获得表权限,CREATE 也不等于能读取所有表。
检查迁移工具的目标 schema
迁移工具若默认写入 public,而团队采用专用 schema,应先调整目标 schema 或 search_path。不要为了让迁移脚本继续运行,就把 public 的写入权授给 PUBLIC。
PostgreSQL 文档提醒:把不可信用户可写的 schema 放进 search_path 有安全风险。权限修复应围绕明确角色与明确 schema。
在受控环境应用最小授权
先备份权限清单,确认由有授权资格的角色执行 GRANT。需要复现多角色部署时,可使用 萤光云 或 LightNode 的隔离实例,避免复制生产数据和密码。
授权后重新建立应用连接,确认连接池没有继续使用旧会话状态;按最小权限原则保留角色分工。
分别验收对象访问和建表
以应用角色执行实际查询,以迁移角色执行受控迁移。两类角色应各自完成预期操作,同时不能获得不需要的创建权或表访问权。 如果新表仍无法读取,还需检查表级授权与默认权限设置。
FAQ
授予数据库 CONNECT 后为什么还报错?CONNECT 只允许进入数据库,不自动授予 schema 与表权限。
可以执行 GRANT ALL ON SCHEMA public TO PUBLIC 吗?不建议。它会把权限扩大到所有角色,先找出实际业务角色和必要操作。
温馨提示
权限变更要留下角色、数据库、schema 和操作范围记录。 PostgreSQL 的升级路径会影响默认权限,迁移到新实例后应重新核对 ACL。


