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。

相关推荐
东风破_7 小时前
danci 2:创建的单词书到底存在哪里?从 Supabase 一路理解 ORM、Drizzle 和 RLS
数据库·后端·node.js
贝锐9 小时前
从国产化信创设备到商用安卓终端,向日葵如何帮助企业实现统一运维管理?
linux·运维·远程控制
橙子家9 小时前
OSS 文件上传的几个风险点和解决方案
数据库
Julien200410 小时前
调查和解决 SELinux 问题
linux·运维·服务器·网络·学习方法
2601_9620664910 小时前
【Sql Server】Update中的From语句,以及常见更新操作方式
android·java·数据库
愤怒的苹果ext11 小时前
MySQL Shell备份恢复数据库
数据库·mysql·备份恢复·mysqlsh
天远Date Lab11 小时前
零信任架构实战:基于天远双人婚姻评估查询构建自动化房产按揭联合审查网关
运维·人工智能·架构·自动化
2601_9620746812 小时前
自己编译RustDesk,并将自建ID服务器和key信息写入客户端
运维·服务器
小张同学a.12 小时前
Docker 容器实战 1—— docker 基础与镜像构建
linux·运维·docker·容器
大模型丫丫13 小时前
Hermes Agent:轻量级智能体框架实战指南
大数据·运维·服务器