一、先看 PostgreSQL 的层级
PostgreSQL 的对象层级可以理解为:
|
|
也就是说,PostgreSQL 的 database 下面还有一层 schema。表、视图、函数等对象并不是直接属于 database,而是属于 database 里的某个 schema。
例如:
|
|
这里 public.orders 和 sales.orders 可以同时存在,因为它们位于不同 schema,完整名称不同。
二、schema 是什么
schema 可以理解为 database 内部的命名空间。
它主要解决四个问题:
|
|
例如一个 ERP 系统可以这样设计:
|
|
这样比所有表都放在 public 里更清晰,也更容易授权。
三、public schema 是什么
创建一个 PostgreSQL database 后,默认通常会有一个名为 public 的 schema。
例如:
|
|
连接到 testdb 后,如果直接建表:
|
|
在默认 search_path 下,这张表通常会创建到:
|
|
也就是等价于:
|
|
所以 public 不是特殊数据库,它只是 PostgreSQL 默认创建的一个 schema。
四、public schema 和 PUBLIC 角色不是一回事
这里非常容易混淆。
|
|
看这条 SQL:
|
|
第一个 public 是 schema 名:
|
|
第二个 PUBLIC 是所有用户:
|
|
完整意思是:
|
|
它不是删除 public schema,也不是禁止所有用户永远创建对象,而是取消默认的“人人都能在 public 里创建对象”的行为。
五、为什么要回收 public schema 的 CREATE 权限
在企业环境里,通常不希望所有用户都能在 public schema 里随便建表、建函数、建对象。
例如你创建了一个只读用户:
|
|
如果这个用户仍然有:
|
|
那么它虽然不能改已有业务表,但仍可能自己创建对象。这与“只读用户”的设计目标不一致。
因此常见安全基线是:
|
|
然后谁确实需要创建对象,再单独授权:
|
|
这体现的是最小权限原则:
|
|
六、如果还需要用户建表,是否冲突
不冲突。
REVOKE CREATE ON SCHEMA public FROM PUBLIC 只是取消“所有用户默认拥有”的权限。
如果某个用户确实需要在 public schema 里建表,可以再单独执行:
|
|
结果是:
|
|
更推荐的方式是不要让应用用户在 public schema 里建表,而是创建独立业务 schema:
|
|
然后业务对象使用:
|
|
七、USAGE 和 CREATE 的区别
schema 上最常见的两个权限是:
|
|
例如只读用户通常需要:
|
|
如果没有 USAGE:
|
|
即使有 orders 表的 SELECT 权限,也可能报 schema 权限错误。
如果要允许用户建表:
|
|
其中:
|
|
八、search_path 是什么
search_path 是 PostgreSQL 用来解析未加 schema 前缀对象名的搜索路径。
查看当前搜索路径:
|
|
常见默认值类似:
|
|
如果执行:
|
|
PostgreSQL 会按 search_path 顺序查找 orders 表。
例如:
|
|
此时:
|
|
PostgreSQL 会先找:
|
|
如果没有,再找:
|
|
可以为角色设置默认搜索路径:
|
|
也可以为某个数据库中的某个角色设置:
|
|
企业环境中建议业务 SQL 尽量明确 schema,或者统一设置 search_path,避免同名表导致访问错对象。
九、PostgreSQL 和 MySQL 的区别
MySQL 中:
|
|
基本可以认为是同义语句。
MySQL 常见层级:
|
|
表完整名通常是:
|
|
PostgreSQL 中:
|
|
连接到 shop database 后,表完整名通常是:
|
|
如果从整体层级看,可以说是:
|
|
但在 SQL 中通常不写 database 前缀,因为 PostgreSQL 普通 SQL 不能像 MySQL 那样直接用 db.table 跨库访问。
对比总结:
| 项目 | MySQL | PostgreSQL |
|---|---|---|
| database 和 schema | 基本同义 | database 下还有 schema |
| 表完整名 | database.table |
schema.table |
| 默认对象空间 | 当前 database | 当前 database 的 public schema |
| 跨库查询 | 常见 db.table |
普通 SQL 不能直接跨 database |
| 权限隔离 | 常按 database 隔离 | 可按 database + schema + object 隔离 |
十、企业中如何使用 schema
不建议所有业务表都堆在 public。
更推荐:
|
|
例如:
|
|
这样权限边界更清楚:
|
|
十一、总结
PostgreSQL 中:
|
|
安全实践上建议:
|
|
然后为业务创建独立 schema:
|
|
理解 schema 和 public,是继续学习 PostgreSQL 授权、只读用户、默认权限和企业权限治理的基础。