今天客户的备份一体机在恢复一个 PDB 时报 ORA-65085,第一反应很容易落到”备份软件不兼容”。现场查下来,两个 CDB 里各躺着一个建库之后从未打开过的 PDB,状态是 “NEW”;而恢复流程需要以只读方式打开它,Oracle 恰好不允许这样打开一个没被读写打开过的库。
把它们正常打开,第一层问题就消失了。第二个库在打开时又冒出 ORA-00600,根因不在 PDB 本身,而是一个 C## 公共用户的密码版本只有 10G。下面记录一下这2个问题。
现象:只读打开被挡住
备份一体机在恢复校验阶段需要把目标 PDB 挂起来,以只读方式打开、核对内容再执行备份。这次打开直接失败:
SQL> alter pluggable database salespdb open read only;
alter pluggable database salespdb open read only
*
ERROR at line 1:
ORA-65085: cannot open pluggable database in read-only mode
顺着 CDB 往下查,两个 CDB 的 dba_pdbs 里都躺着一个 status 为 NEW 的 PDB,建出来之后一直没有被打开过:
SQL> select con_id, pdb_name, status from dba_pdbs;
CON_ID PDB_NAME STATUS
---------- ---------- --------------------
2 PDB$SEED NORMAL
3 PDB11 NORMAL
4 PDB12 NORMAL
5 PDB13 NORMAL
6 SALESPDB NEW
Oracle online DOC. The status of the PDB dba_pdbs. Possible values are as follows:
NEW– The PDB has never been opened since its creation. It needs to be opened in read-only mode for Oracle to perform the necessary steps to complete the integration of the PDB into the CDBNORMALand mark it as completeREAD WRITE. Attempting to open the PDB in read-only mode will result in an error.NORMAL– The PDB is ready for use.UNPLUGGED– The PDB has been disconnected. In this case, the only possible operation isDROP PLUGGABLE DATABASE:NEEDS UPGRADE– The PDB needs to be upgraded to the version of the connected CDB.CONVERTING– The non-CDB is being plugged into the CDB and is undergoing the necessary conversions to function like a real PDB.UNUSABLE– The PDB is being created, or an unrecoverable error occurred during creation. The PDBUNUSABLEcannot be opened while its state is set to this. If the PDB is maintaining this state due to an error that occurred during creation, the only possible action is deletion. You can check the alert log to determine if an error occurred during PDB creation.
NEW 是 PDB 创建后从来没有打开过, 需要第一次以read write打开。
NEW 状态的 PDB 必须先读写打开一次
Oracle 对这个报错的官方口径写得很直白:原因是该 PDB 创建后未被打开,或者 CDB 的 undo 模式变更后没有以读写模式打开过;建议动作是先以读写或受限模式打开,再谈只读。
本地复现一遍,链条完整可见:
复现:NEW 状态被只读打开拒绝,读写打开后转为 NORMAL
SQL> CREATE PLUGGABLE DATABASE salespdb ADMIN USER salesadm IDENTIFIED BY pwd;
Pluggable database created.
SQL> alter pluggable database salespdb open read only;
ERROR at line 1:
ORA-65085: cannot open pluggable database in read-only mode
SQL> alter pluggable database salespdb open;
Pluggable database altered.
SQL> select con_id, pdb_name, status from dba_pdbs;
CON_ID PDB_NAME STATUS
---------- ---------- --------------------
6 SALESPDB NORMAL
机制并不复杂:PDB 第一次打开要完成一整套初始化,包括打开数据文件、建立运行所需的元信息,这些动作都需要写。只读打开没有写入能力,所以这条路被封死。open 之后状态从 NEW 变 NORMAL,此后只读打开、备份、恢复都恢复正常。
现场处置就落在这里:把两个库里的 NEW PDB 逐个 open。第一个库一次通过,第二个库在这一步翻了车。
报错2:读写打开又触发 ORA-00600
第二个 CDB 里的 NEW 库是 XTSYHDC825,把它读写打开:
SQL> alter pluggable database XTSYHDC825 open;
alter pluggable database XTSYHDC825 open
*
ERROR at line 1:
ORA-00600: internal error code, arguments: [kpdbsecModAdmPrvOrPasswd:crt_no_priv_or_passwd], [], [], [], [], [], [], [], [], [], [], []
ORA-00600 的参数已经把方向指出来了:kpdbsecModAdmPrvOrPasswd 是打开 PDB 时为公共用户同步口令与授权的内部逻辑,crt_no_priv_or_passwd 说明它取不到可用的权限或口令。于是去看公共用户:
SQL> select username, password_versions from dba_users order by 1;
...
C##ZxxGSADMIN 11G 12C
C##ZXXXMONITOR 11G 12C
C##ZXXXSDBA 10G
...
同一个 CDB 里的三个 C## 公共用户,只有 C##ZXXXSDBA 的密码版本停在 10G。打开一个 NEW 状态的 PDB 时,Oracle 要为该 PDB 内的公共用户建立口令与授权映射,这一步要求账号至少有 11G 的 verifier:10G 是早期的大小写不敏感版本,11G 起是 SHA-1 以及 SHA-2 系算法。只有 10G 时,这段逻辑拿不到可用凭证,级联抛出ora-600。
MOS 文档 KB90897 记录的就是这个场景:ORA-00600 [kpdbsecModAdmPrvOrPasswd: crt_no_priv_or_passwd] while trying to Open New PDB。
它的处置方式删掉该C##用户,本案建议如果用户还有用的情况下采用的方式:重置该用户密码,让 PASSWORD_VERSIONS 补回 11G,再打开这个 NEW 库。
重置密码后版本补齐,NEW 库一次打开
SQL> alter user C##ZOESYSDBA identified by "新口令";
User altered.
SQL> select username, password_versions from dba_users where username = 'C##ZOESYSDBA';
USERNAME PASSWORD_VERSIONS
------------------- ------------------
C##ZxxxSYSDBA 11G 12C
SQL> alter pluggable database XTSYHDC825 open;
Pluggable database altered.
还有一条线索值得记下:这台库的 sqlnet.ora 里,SQLNET.ALLOWED_LOGON_VERSION_SERVER 与 SQLNET.ALLOWED_LOGON_VERSION_CLIENT 都被设成了 8,通常是为了让老客户端连得上。这种放低登录版本下限的配置,是账号只生成 10G verifier 的常见来源。如果重置密码后 11G 版本仍不出现,先回来看这个参数,评估完客户端兼容性再动它,别只盯着 PDB 找原因。
两种修法怎么选
现场其实有两条路:在库端把这些 NEW PDB 修好,或者在软件端把它们排除在本次处理范围之外。后一条是客户升级 备份软件 时想到的规避方案,把 NEW 状态的库排除掉,恢复流程就不再撞上它。
| 路径 | 具体做什么 | 见效与代价 |
| 库端先修 | 把 NEW 状态的 PDB 逐个 open;遇到 ORA-00600 的,先补齐该 C## 用户的密码版本 | 当场见效,不需要改动备份软件,需要 CDB 级权限;首次打开会执行初始化,占一点 I/O |
| 软件端规避 | 升级 备份软件 时把 NEW 状态的库排除在只读打开范围内 | 不改库,风险最小,升级窗口内见效只是绕开,隐患留在库里 |
| 本次结论 | 选库端先修 | 两个库各只有一个 NEW 库,修复量小,顺手把状态清干净 |
判断标准不是哪条更快,而是这个 NEW 库还会不会被别的流程碰到。只要备份、升级、迁移里还有”以只读方式打开”的动作,绕开就只是把问题挪到下一个窗口。
复盘:下次照这个顺序查
- 打开任何 PDB 之前,先查 select con_id, pdb_name, status from dba_pdbs,确认有没有 NEW。
- 看到 NEW,直接 alter pluggable database 库名 open,不要先试 read only。
- open 报出 kpdbsecModAdmPrvOrPasswd,转去查 dba_users 里 C## 账号的 PASSWORD_VERSIONS,缺 11G 就重置密码。
- 建完 PDB 立刻打开一次再按需关闭,别让 NEW 状态留到恢复窗口里。
- 以只读方式打开 PDB 的工具,把状态检查前置成例行步骤,比在恢复窗口里报错更合理。