REVOKE后报ORA-01536或ORA-01950并非权限未撤除,而是DBA/RESOURCE角色隐含的UNLIMITED TABLESPACE被连带回收,导致用户在所有表空间配额为0;需查DBA_SYS_PRIVS确认该权限是否存在,并用DBA_TS_QUOTAS验证实际配额,空结果表示真无配额;应按需授予有限配额(如ALTER USER user_name QUOTA 100M ON users),尤其勿漏TEMP表空间。
为什么REVOKE后应用还报ORA-01536或ORA-01950
不是权限没撤掉,而是unlimited tablespace被连带回收了。oracle里dba或resource角色自带unlimited tablespace系统权限;一旦revoke dba from user或revoke resource from user,这个隐式权限就没了,用户在所有表空间的配额变成0——建表、插入、甚至排序(用到temp)都会失败,但错误不指向“权限缺失”,而是具体报ora-01536: space quota exceeded for tablespace 'users'或ora-01950: no privileges on tablespace 'users'。
查清楚到底缺什么配额,别只盯着角色
执行REVOKE后必须立刻验证两点:
- 查
DBA_SYS_PRIVS确认UNLIMITED TABLESPACE是否还在:SELECT privilege FROM dba_sys_privs WHERE grantee = 'USER_NAME' AND privilege = 'UNLIMITED TABLESPACE'; - 查
DBA_TS_QUOTAS看实际配额:SELECT tablespace_name, bytes/1024/1024 MB FROM dba_ts_quotas WHERE username = 'USER_NAME';——如果结果为空,说明该用户在所有表空间都无配额
注意:DBA_TS_QUOTAS不显示UNLIMITED配额,它只列有限值;空结果 ≠ 有无限配额,而是真没配额。
补配额比重授UNLIMITED TABLESPACE更安全
直接GRANT UNLIMITED TABLESPACE TO user_name会把问题打回原形,且可能被下次REVOKE RESOURCE再次带走。推荐按需设有限配额:
- 给默认表空间加配额:
ALTER USER user_name QUOTA 100M ON users; - 给临时表空间也补上(否则
ORDER BY、GROUP BY可能失败):ALTER USER user_name QUOTA 50M ON temp; - 如果业务明确需要某张表所在表空间,只放开那个:
ALTER USER user_name QUOTA UNLIMITED ON app_data;
别漏掉temp表空间——它不存数据,但没配额会导致SQL执行中途报错,且错误日志里往往不提示表空间名。
脚本批量回收时最常忽略的三个点
写PL/SQL自动REVOKE很省事,但以下三点一漏,应用就断:
- 没过滤
SYS、SYSTEM等内置账户:WHERE grantee NOT IN ('SYS', 'SYSTEM', 'OUTLN', 'DBSNMP')必须加上 - 没检查用户当前是否在线:
SELECT username FROM v$session WHERE username = 'USER_NAME',正在跑批的用户被撤权后新SQL立即失效,但旧事务还能撑一会儿,容易误判“撤成功了” - 没清理角色继承链:比如
REVOKE SELECT ON emp FROM scott失败,大概率是因为scott是通过hr_role间接获得的——得先查DBA_ROLE_PRIVS和ROLE_TAB_PRIVS,再决定是REVOKE hr_role FROM scott还是REVOKE SELECT ON emp FROM hr_role
真正卡住的从来不是REVOKE语法,而是权限来源没理清、配额没补上、或者忘了TEMP表空间那1MB配额。











