必须先切换到目标PDB再改密码,因为Oracle 12c+多租户架构中本地用户仅存在于对应PDB的数据字典内,CDB$ROOT中不可见且无法操作;在错误容器执行ALTER USER IDENTIFIED BY会导致命令看似成功但实际未生效。
在pdb容器内执行 alter user ... identified by 是唯一能正确修改本地pdb用户密码的方式;连错容器(比如在cdb$root里改pdb本地用户)会导致密码看似更新、实际无效。
为什么必须先切换到目标PDB再改密码
Oracle 12c+ 的多租户架构下,用户归属严格绑定容器:本地用户(如 hr、scott 在 PDB 中创建)只存在于对应 PDB 的数据字典中。CDB$ROOT 中查不到他们,也无法对其执行密码修改。
- 你在 CDB$ROOT 执行
ALTER USER hr IDENTIFIED BY newpass→ 报ORA-01918: user 'HR' does not exist - 你在 PDB 中执行但没切换容器(仍连着 CDB$ROOT)→ 命令不报错但不生效,应用仍连不上
- 正确做法:先确认当前容器,再显式切换,最后改密
如何确认并切换到正确的PDB容器
用 SYS_CONTEXT('USERENV', 'CON_NAME') 查当前容器名,再用 ALTER SESSION SET CONTAINER = <pdb_name> 切换。注意:该语句要求你有 SET CONTAINER 权限(通常 SYSDBA 或 COMMON USER 具备)。
- 查当前容器:
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') FROM DUAL; - 查所有 PDB 状态:
SELECT con_id, name, open_mode FROM v$pdbs; - 切换到目标 PDB:
ALTER SESSION SET CONTAINER = orclpdb; - 切换后验证:
SHOW CON_NAME或再跑一遍SYS_CONTEXT查询
改密码时的常见错误和绕过点
即使容器正确,仍可能因权限、字符集或 profile 限制失败。最典型的是密码复杂度校验或字符集不兼容导致的静默失败(命令返回成功,但登录仍用旧密码)。
- 若报
ORA-28003: password verification for the specified password failed→ 检查用户 profile 的PASSWORD_VERIFY_FUNCTION - 若改密后应用仍连不上 → 不是密码没生效,而是连接池缓存了旧凭据,需重启应用或刷新连接池
- 若提示字符集问题(如中文密码报错)→ 避免使用非 ASCII 字符,改用字母+数字+符号组合,例如
Test6530 - 不要在 PDB 中对
C##开头的公共用户改密 —— 他们只存在于 CDB$ROOT,必须回 root 改
验证密码是否真正更新成功
别只信 SQL*Plus 的 “Statement processed” 提示。真正有效的标志是:用新密码能登录,且 dba_users 中该用户的 password_version 已更新(如从 10G 11G 变为 12C),且 account_status 为 OPEN。
- 登录验证:
sqlplus hr/newpass@//localhost:1521/orclpdb - 查密码状态:
SELECT username, account_status, password_version FROM dba_users WHERE username = 'HR'; - 如果仍显示旧密码哈希或
account_status是EXPIRED(GRACE)→ 说明改密未穿透到底层,重试前先确认容器和权限
最容易被忽略的一点:ALTER USER ... IDENTIFIED BY 在 PDB 中执行时,CONTAINER 子句不可用(会报 ORA-65050),也不需要加 —— 它天然作用于当前容器。硬加反而出错。


















