<p>MySQL 8.0+ 的 Schema 级权限即 DATABASE 级权限,直接使用 GRANT ... ON database_name.* 实现,无需模拟;database_name 必须真实存在且大小写敏感,不支持通配符库名,新表自动继承权限。</p>

MySQL 8.0+ 怎么模拟 Oracle 的 Schema 级权限(即 DATABASE 级)
MySQL 没有 SCHEMA 这个独立权限对象,它的 SCHEMA 就是 DATABASE,权限粒度天然落在库级别。所以“Schema 级权限管理”在 MySQL 里直接对应 GRANT ... ON database_name.*,不是模拟,而是本来就是这么用的。
常见错误是照着 Oracle 写法去试 GRANT SELECT ON schema_name.table_name —— MySQL 会报错 ERROR 1142 (42000): SELECT command denied to user,因为没指定库名或用了不存在的 schema 名。
-
database_name必须真实存在,且名字要和SHOW DATABASES输出完全一致(区分大小写取决于lower_case_table_names设置) - 不能对通配符库名(如
`test%`)授权,MySQL 不支持模式匹配的库名授权 -
GRANT SELECT ON mydb.* TO 'u'@'h'授予的是该库下所有*当前存在且用户可见*的表权限;新创建的表自动继承(只要用户有SELECTon db.*)
PostgreSQL 怎么做到接近 Oracle 的 Schema 权限隔离
PostgreSQL 的 SCHEMA 是明确的一等公民,但权限不是默认绑定到 schema 的——必须显式 GRANT 到 schema 本身,再配合 GRANT 到 schema 下的对象类型(如 TABLES),才能实现类似 Oracle 的控制。
典型踩坑:只执行 GRANT USAGE ON SCHEMA myschema TO u,结果用户仍无法查表——因为 USAGE 只允许访问 schema 命名空间,不包含表数据权限。
- 必须组合两条命令:
GRANT USAGE ON SCHEMA myschema TO u+GRANT SELECT ON ALL TABLES IN SCHEMA myschema TO u - 新表默认不继承权限,需运行
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT SELECT ON TABLES TO u才能覆盖后续新建表 - 如果 schema 属于非
public用户(比如myschemaowner 是app_owner),则app_owner必须先GRANT USAGE给目标用户,否则连myschema.table都解析不了
GRANT 语句中 ON 后面的范围怎么选才不越权
权限范围写太宽(比如 ON *.*)或太窄(比如 ON db.t 却忘了 schema 权限)都会导致权限失控。关键看实际最小必要集。
例如应用账号只需要读取订单相关表:它不该有 ON db.*,而应限定为 ON db.orders TO u(MySQL)或 ON TABLE db.orders TO u(PostgreSQL,前提是已给 schema usage)。
- MySQL:优先用
db.*,除非业务明确要求单表隔离(此时注意触发器、视图依赖可能绕过限制) - PostgreSQL:
ON SCHEMA s控制命名空间访问,ON TABLES IN SCHEMA s控制数据访问,两者缺一不可 - SQL Server 类似 PostgreSQL,但用
SCHEMA :: s语法,且需额外GRANT SELECT ON SCHEMA :: s(注意双冒号)
权限生效后为什么还是报 “Access denied”
最常被忽略的是 host 匹配和权限缓存。MySQL 的 user@host 是完整认证单元,'u'@'localhost' 和 'u'@'127.0.0.1' 是两个不同账号;PostgreSQL 的 pg_hba.conf 规则顺序也直接影响是否走到权限检查环节。
- MySQL 执行完
GRANT后,记得FLUSH PRIVILEGES(仅当手动改了mysql.user表才必须;正常GRANT会自动刷新) - PostgreSQL 修改
pg_hba.conf后必须pg_ctl reload或SELECT pg_reload_conf(),否则连接层就拒绝了,根本不会查权限 - 检查实际连接使用的 host:用
SELECT USER(), CURRENT_USER();看 MySQL 实际匹配的账号;PostgreSQL 用SELECT session_user, current_user;
权限模型本身不复杂,难的是把“谁、从哪来、想干啥、系统认不认”这四件事对齐。漏掉任意一环,GRANT 就等于白写。










