ODA/Oracle 19c CDB/PDB 环境下报错ORA-65162:common user密码过期问题排查与处理_2026-05-15

1、问题现象

业务系统连接 Oracle 数据库时失败,页面提示类似:

复制代码
ORA-65162: The password of the common user has expired

从报错可以看出,这不是网络端口问题,也不是监听服务异常,而是 Oracle common user 密码过期

本次涉及两个 CDB:

复制代码
MESCDB
UTF8CDB

相关用户为:

复制代码
C##MESCDBFLINK
C##UTF8CDBFLINK

这类 C## 开头的用户,一般属于 CDB common user


二、确认当前 CDB/PDB 环境

登录数据库服务器后,进入对应实例:

复制代码
su - oracle
export ORACLE_SID=mescdb1
sqlplus / as sysdba

查看 PDB:

复制代码
show pdbs;

示例结果:

复制代码
CON_ID  CON_NAME   OPEN MODE
------  --------   ----------
2       PDB$SEED   READ ONLY
3       MESDB      READ WRITE
5       RZMESDB    READ WRITE

确认当前容器:

复制代码
show con_name;

如果是 common user,建议在 CDB$ROOT 下处理。

复制代码
alter session set container=CDB$ROOT;

三、查询用户状态

先通过 cdb_users 查询用户状态:

复制代码
set lines 200 pages 200
col con_name for a15
col username for a35
col account_status for a30
col expiry_date for a20
col profile for a25
col common for a8

select u.con_id,
       c.name con_name,
       u.username,
       u.account_status,
       u.expiry_date,
       u.profile,
       u.common
from cdb_users u
join v$containers c on u.con_id = c.con_id
where u.username = upper('C##MESCDBFLINK')
order by u.con_id;

排查结果如下:

复制代码
CON_ID  CON_NAME   USERNAME        ACCOUNT_STATUS  EXPIRY_DATE           PROFILE   COMMON
------  --------   --------------  --------------  -------------------   -------   ------
1       CDB$ROOT   C##MESCDBFLINK  EXPIRED         2026-05-13 09:57:06   DEFAULT   YES
3       MESDB      C##MESCDBFLINK  OPEN                                  DEFAULT   YES
5       RZMESDB    C##MESCDBFLINK  OPEN                                  DEFAULT   YES

这里可以明确看出:

复制代码
CDB$ROOT 下账号状态为 EXPIRED

虽然 PDB 中显示为 OPEN,但是 common user 在 CDB$ROOT 中密码过期后,连接 PDB 仍然会失败。


四、创建专用 Profile,设置密码永不过期

生产环境不建议直接修改 DEFAULT profile,因为可能影响其他用户。

更稳妥的方式是:单独创建业务账号专用 profile

复制代码
alter session set container=CDB$ROOT;

先检查 profile 是否存在:

复制代码
select profile
from dba_profiles
where profile = 'C##APP_PROFILE'
group by profile;

如果不存在,创建:

复制代码
create profile C##APP_PROFILE limit
  PASSWORD_LIFE_TIME UNLIMITED
  PASSWORD_GRACE_TIME UNLIMITED;

说明:

复制代码
PASSWORD_LIFE_TIME  UNLIMITED  表示密码永不过期
PASSWORD_GRACE_TIME UNLIMITED  表示不进入密码过期宽限期

五、将 common user 切换到新 Profile

C##MESCDBFLINK 为例:

复制代码
alter user C##MESCDBFLINK profile C##APP_PROFILE container=all;

然后使用原密码重置并解锁:

复制代码
alter user C##MESCDBFLINK identified by "原密码" account unlock container=all;

如果密码中包含特殊字符,比如 #,必须使用双引号包起来:

复制代码
alter user C##MESCDBFLINK identified by "******" account unlock container=all;

注意:

这里建议使用原密码重置,这样业务系统连接配置不用同步修改。


六、验证处理结果

再次查询用户状态:

复制代码
select u.con_id,
       c.name con_name,
       u.username,
       u.account_status,
       u.expiry_date,
       u.profile,
       u.common
from cdb_users u
join v$containers c on u.con_id = c.con_id
where u.username = 'C##MESCDBFLINK'
order by u.con_id;

正常结果应类似:

复制代码
CON_ID  CON_NAME   USERNAME        ACCOUNT_STATUS  EXPIRY_DATE  PROFILE          COMMON
------  --------   --------------  --------------  -----------  ---------------  ------
1       CDB$ROOT   C##MESCDBFLINK  OPEN                         C##APP_PROFILE   YES
3       MESDB      C##MESCDBFLINK  OPEN                         C##APP_PROFILE   YES
5       RZMESDB    C##MESCDBFLINK  OPEN                         C##APP_PROFILE   YES

重点看三项:

复制代码
ACCOUNT_STATUS = OPEN
EXPIRY_DATE    为空
PROFILE        = C##APP_PROFILE

再确认 profile 策略:

复制代码
select profile, resource_name, limit
from dba_profiles
where profile = 'C##APP_PROFILE'
and resource_name in (
  'PASSWORD_LIFE_TIME',
  'PASSWORD_GRACE_TIME',
  'FAILED_LOGIN_ATTEMPTS',
  'PASSWORD_LOCK_TIME'
)
order by resource_name;

示例结果:

复制代码
PROFILE          RESOURCE_NAME          LIMIT
---------------  ---------------------  ---------
C##APP_PROFILE   FAILED_LOGIN_ATTEMPTS  DEFAULT
C##APP_PROFILE   PASSWORD_GRACE_TIME    UNLIMITED
C##APP_PROFILE   PASSWORD_LIFE_TIME     UNLIMITED
C##APP_PROFILE   PASSWORD_LOCK_TIME     DEFAULT

这里说明:

复制代码
密码已经永不过期;
但如果密码连续输错,仍然可能按 DEFAULT 策略锁定。

七、CDB common user 和 PDB local user 的区别

本次处理的两个用户:

复制代码
C##MESCDBFLINK
C##UTF8CDBFLINK

都属于 common user,特点是:

复制代码
用户名以 C## 开头
COMMON = YES

这种用户应在:

复制代码
CDB$ROOT

中处理,并使用:

复制代码
container=all

例如:

复制代码
alter user C##MESCDBFLINK profile C##APP_PROFILE container=all;

如果是普通业务用户,例如:

复制代码
STEELMES
MES_ADMIN
HYTOMES
QMS
LZMES
RZMES

如果查询结果为:

复制代码
COMMON = NO

则说明它们是 PDB local user,只属于某个具体 PDB。

这类用户不需要在 CDB$ROOT 中修改,直接切换到所属 PDB 处理即可:

复制代码
alter session set container=MESDB;

create profile APP_PROFILE limit
  PASSWORD_LIFE_TIME UNLIMITED
  PASSWORD_GRACE_TIME UNLIMITED;

alter user STEELMES profile APP_PROFILE;

如果账号已过期或锁定,再用原密码重置解锁:

复制代码
alter user STEELMES identified by "原密码" account unlock;

八、总结

本次问题的核心原因是:

复制代码
Oracle CDB common user 在 CDB$ROOT 中密码过期,导致业务系统连接 PDB 失败。

关键排查 SQL:

复制代码
select u.con_id,
       c.name con_name,
       u.username,
       u.account_status,
       u.expiry_date,
       u.profile,
       u.common
from cdb_users u
join v$containers c on u.con_id = c.con_id
where u.username = upper('用户名')
order by u.con_id;

关键处理思路:

复制代码
common user:在 CDB$ROOT 中处理,使用 container=all
local user :进入对应 PDB 中处理,不使用 container=all

最终处理方式:

复制代码
创建专用 profile
设置 PASSWORD_LIFE_TIME 为 UNLIMITED
设置 PASSWORD_GRACE_TIME 为 UNLIMITED
将业务连接用户切换到该 profile
使用原密码重置并解锁账号

一句话总结:
C## 用户看 CDB$ROOT,普通业务用户进 PDB;谁家的账号谁家管,别在生产环境里乱改 DEFAULT。

相关推荐
dinglu1030DL1 小时前
CSS如何利用Flex实现悬浮的侧边按钮组_利用fixed定位与flex布局组合
jvm·数据库·python
Jetev1 小时前
如何利用SQL子查询进行非结构化数据处理_文本匹配
jvm·数据库·python
老纪1 小时前
c++怎么在Windows下设置文件的安全访问控制列表(ACL)权限【底层】
jvm·数据库·python
wjykp1 小时前
5.cypher语句组合与复杂操作
linux·前端·javascript
其实防守也摸鱼1 小时前
[特殊字符] Docker + LMArena2API 部署全流程:从环境准备到接口调用,一步到位
运维·网络·安全·web安全·docker·容器·大模型
難釋懷1 小时前
Redis网络模型-异步IO
网络·数据库·redis
志栋智能1 小时前
超自动化巡检:如何应对海量增长的基础设施?
运维·自动化
苏宸啊1 小时前
磁盘结构、存储原理
linux
代码讲故事1 小时前
Redis生产环境批量的key需要删除,如何优雅实现且不影响线上环境?有密码认证的如何实现批量删除?有哪些实现方法?
运维·redis·缓存·高并发·删除·批量·生产环境