🏺 第12章 用户管理与权限分配
📄 一句话概括

建用户的语法很长,但只有三件事必须想清楚:怎么认证、放哪个表空间、给多少配额。 配额默认是 0——新用户不给配额,连一张表都建不了, 报 ORA-01950。这是最容易卡住新手的一条。

📝 本章和前面几章的关系

12.1 讲「用户和模式是一回事」。这一篇讲建用户时的具体参数。 参数不多,但每一个都对应一个常见的坑。 这一篇的重点不是语法,是三个「以为是这样、其实不是」: 以为有权限就能建表(还要配额)、以为改密码能踢掉旧会话(不能)、 以为改默认表空间会搬数据(不会)。

一、认证方式:三种

方式 写法 谁验证 适合
密码 IDENTIFIED BY 密码 数据库 普通业务账号
外部 IDENTIFIED EXTERNALLY 操作系统 运维统一管的系统账号
全局 IDENTIFIED GLOBALLY LDAP/AD 已有域认证的公司

密码认证是默认的,也是最常见的。 密码在 11g 之后默认区分大小写—— 老系统升级上来要特别注意,因为 10g 及以前是不区分的,升级后老密码可能登不上。 外部认证的好处是「不用在数据库里存密码」, 坏处是「任何能登录这台机器的人,都能用这个账号连库」—— 所以它只适合「机器本身就是受控的」场景。 全局认证的好处是「离职在 AD 里停用,数据库自动进不来」,这一个理由就够很多公司选它了。

二、表空间与配额:两个不同的东西

默认表空间:DEFAULT TABLESPACE users—— 决定「这个用户新建的表放哪」,要提前建好这个表空间。 配额:QUOTA 100M ON users——决定「这个用户能在 users 表空间里用多少空间」。 两个概念容易混,但性质完全不同: 表空间是「仓库」,配额是「这个人在仓库里能占多少货架」。 表空间可以很大,但配额给小了,照样存不进。 配额默认是 0。 也就是说:CREATE USER 之后不给配额,这个用户一张表都建不了, 报 ORA-01950: 对表空间 'USERS' 无权限。 注意这个报错措辞很容易误导——它说的是「无权限」,其实是「没配额」。

三、改用户:ALTER USER 能改什么

要改什么 怎么写 立即生效吗
密码 ALTER USER u IDENTIFIED BY 新密码 是,但旧会话不断
配额 ALTER USER u QUOTA 200M ON users 是
锁定账户 ALTER USER u ACCOUNT LOCK 是,立即踢不下来但连不进
默认表空间 ALTER USER u DEFAULT TABLESPACE tbs 只影响新对象
PROFILE ALTER USER u PROFILE p 下次登录生效

「改密码但旧会话不断」这一条要重点说。 改完密码,已经连着的会话照常能干活——因为会话建立时已经验证过了,之后不再验。 所以「怀疑密码泄露、紧急改密」这个动作,改完不等于把坏人赶出去。 要断掉旧会话,得用 ALTER USER ... PASSWORD EXPIRE 让密码立刻过期, 或者直接 ALTER SYSTEM KILL SESSION。 「改默认表空间不搬数据」也常被误会。 它只影响「以后建的表的默认位置」,已经建好的表还在原来的表空间里—— 要搬得单独 ALTER TABLE ... MOVE TABLESPACE ...,而且那是个重活(要重写全表)。

四、删用户与锁用户

删之前先锁:ALTER USER u ACCOUNT LOCK; 锁住之后,密码正确也连不进。 这是「确定不用了但还不敢删」的最佳状态。 观察一到两个月,确认没有程序还在连,再删。 怎么确认?看审计日志或者 V$SESSION 的历史—— 光看「现在有没有连着」是不够的,因为月结程序可能一个月才跑一次。 真要删的时候别忘了 CASCADE: 没 CASCADE 有对象就删不掉,报 ORA-01922。 但也别顺手就加 CASCADE——它会把对象一起删,删之前先 SELECT 一下这个模式下有什么。

五、动手 Demo:认证、配额、改用户:三个「以为是这样」

这一篇的 Demo 用一张张对照表把参数摆清楚,再用一个配额模型实测「超了会怎样」。 沙箱里没有 CREATE USER,但配额这件事就是个加减法—— 用一个类模拟「已用多少、还剩多少、超了报什么」,能真跑。

# 配额:有权限建表,不等于有空间存表
class User(object):
    def __init__(self, name, quota_mb):
        self.name, self.quota, self.used = name, quota_mb, 0

    def create_table(self, mb):
        if self.used + mb > self.quota:
            raise MemoryError("ORA-01536: 超出表空间 'USERS' 的空间限额")
        self.used += mb
        return "建表成功,已用 %d/%d MB" % (self.used, self.quota)

u = User("scott", 10)
print(u.create_table(4))
print(u.create_table(4))
try:
    print(u.create_table(4))
except MemoryError as e:
    print(e)
print("注意:配额默认是 0,所以新用户不给配额,一张表都建不了。")

实跑输出:

--------------------------------------------------------------------
第五十四课:创建与管理用户——三个必填项
--------------------------------------------------------------------

  **建用户的语法很长,但只有三件事是必须想清楚的:**  **怎么认证、放哪个表空间、给多少配额。**

  一、认证方式:密码、外部、全局
  --------------------------------------------------------------------

  方式 写法                  谁验证
  --------------------------------------------
  密码 IDENTIFIED BY 密码    数据库自己
  外部 IDENTIFIED EXTERNALLY 操作系统
  全局 IDENTIFIED GLOBALLY   LDAP/AD 目录服务
  已选择 3 行
  **密码认证是默认的,也是最常见的。**  **外部认证适合「系统账号统一由运维管」的场景**,
  **全局认证适合「已经有 AD 域」的公司**——
  **好处是「离职在 AD 里停用,数据库也就进不来了」,不用两边维护。**

  二、表空间与配额:能存多少
  --------------------------------------------------------------------

  用户   默认表空间 配额MB 已用MB 剩余MB
  --------------------------------------
  app    USERS      100    0      100
  report USERS      10     0      10
  已选择 2 行
  **`QUOTA` 是「这个用户能在表空间里用多少空间」,不是「表空间一共多大」。**  **默认配额是 0**——
  **也就是说,新建的用户如果不给配额,连一张表都建不了**,
  **报 `ORA-01950: 对表空间 'USERS' 无权限`。**
  **这一条最容易卡住新手:明明给了 `CREATE TABLE` 权限,还是建不了表。**
  **因为「有权限建表」和「有空间存表」是两件事。**

  三、实测:配额用完会怎样
  --------------------------------------------------------------------
  **`report` 配额 10MB 已经用满,剩余 0MB。**

  SQL> INSERT INTO big_table SELECT * FROM huge_source;
  ERROR 位于第 1 行:
  ORA-01536: 超出表空间 'USERS' 的空间限额
  **注意报的是 `ORA-01536`,而且是「插到一半才报」**——
  **不是插入前检查,是写到没空间了才发现。**
  **所以「配额」这个限制,出事的时候往往已经写进去一部分了。**

  四、改用户:ALTER USER 能改什么
  --------------------------------------------------------------------

  要改什么     怎么写                              要不要重连
  ---------------------------------------------------------------------
  改密码       ALTER USER u IDENTIFIED BY 新密码   不要
  改配额       ALTER USER u QUOTA 200M ON USERS    不要
  锁账户       ALTER USER u ACCOUNT LOCK           立即生效
  改默认表空间 ALTER USER u DEFAULT TABLESPACE tbs 不要(只影响新对象)
  改 PROFILE   ALTER USER u PROFILE p              下次登录生效
  已选择 5 行
  **「改默认表空间」这一条容易误会:**  **它只影响「以后新建的对象放哪」,已经建好的表不会搬过去**
  ——  **要搬得单独 `ALTER TABLE ... MOVE TABLESPACE ...`。**
  **改密码之后,已经连着的会话不会被踢掉。**
  **要让旧会话失效,得用 `ALTER USER ... PASSWORD EXPIRE` 或者直接 `KILL SESSION`。**
  **这一点在「怀疑密码泄露,紧急改密」的时候很关键**——  **改完密码不等于把坏人赶出去了。**

第一段是三张表:认证方式、配额、ALTER USER。 这三张表基本覆盖了「建用户」要做的所有决定。 第二段实测配额:配额 10MB,建两张 4MB 的表(用了 8MB),第三张 4MB 就超了。 报的是 ORA-01536,而且真实环境里往往是「插到一半才报」—— 不是插入前检查,是写到没空间了才发现。 第三段那句「配额默认是 0」是最要命的。 新手最常见的卡点就是:给了 CREATE TABLE 权限,建表还是报错。 报错写的是「对表空间无权限」,实际原因是「没配额」。 第四段三张表里,「改密码旧会话不断」和「改默认表空间不搬数据」这两条最容易被忽略。 前者是安全问题(改完密码坏人还在),后者是容量问题(以为搬了其实没搬)。

30 秒实验

  1. 把配额从 10 改成 100,重跑。第三张 4MB 的表就能建成了——配额就是一道加法闸门。
  2. 想想「配额无限」怎么写:QUOTA UNLIMITED ON users。 代价是这个用户能把表空间写满,影响同表空间的其他用户。
  3. 把 ALTER USER u IDENTIFIED BY 新密码 之后加一句「旧会话还在」的验证: 在真实 Oracle 里,改完密码用旧连接执行 SELECT 1 FROM dual 照样成功。

常见误区

  1. 「给了 CREATE TABLE 就能建表」。 还要配额。 配额默认 0,报 ORA-01950,措辞还写着「无权限」,更容易误判。
  2. 「改密码会把旧会话踢掉」。 不会。旧会话在建立时已经验证过,之后不再验密码。
  3. 「改默认表空间会把已有的表搬过去」。 不会,只影响新建的对象。 搬表要 ALTER TABLE ... MOVE TABLESPACE,而且很慢。
  4. 「删用户前不用锁」。 直接删风险高—— 先 ACCOUNT LOCK 观察一两个月,确认没有程序还在连,再删。
自测三问(点开对答案) 1. 配额和表空间是什么关系? —— **表空间是仓库,配额是这个人在仓库里能占多少货架。** **表空间很大,但配额给小了照样存不进。** 2. 新建用户为什么建不了表? —— **配额默认是 0。** 报 `ORA-01950`,措辞是「无权限」,实际是「没配额」。 3. 改密码之后,旧会话会断吗? —— **不会。** 要断得用 `PASSWORD EXPIRE` 或 `KILL SESSION`。 4. 删用户之前推荐做什么? —— **先 `ALTER USER ... ACCOUNT LOCK` 锁账户,观察一段时间再删。**

下一篇讲权限:系统权限管动作,对象权限管对象。 两类权限的分界线很清楚,但很容易混着用。

相关笔记