查补丁历史需综合opatch lsinventory、dba_registry_sqlpatch和v$version三处:前者看二进制层,后者看sql层执行状态,v$version确认版本号更新,缺一不可。
查数据库sql补丁历史,只看 dba_registry_sqlpatch 不够
这个视图确实记录了所有通过 datapatch 应用的sql层补丁(比如ru、rur、ojvm里的字典变更),但它不显示二进制补丁(opatch apply 打的)、也不包含已回滚但未清理的残留记录。直接 select * from dba_registry_sqlpatch 可能让你误以为“没打过补丁”或“全打完了”,其实只是sql部分的快照。
实操建议:
- 必须搭配
dba_registry_history一起查:它记录所有注册过的补丁动作(包括失败、回滚、手动插入),字段ACTION和STATUS是关键判断依据 - 注意
ACTION_TIME是本地时区时间,不是UTC;如果跨时区运维,别靠它比对执行顺序 - 若发现某条记录
STATUS = 'FAILED'但数据库运行正常,先别急着删——可能是SQL补丁被跳过(如因对象无效),得结合datapatch -verbose日志确认
opatch lsinventory 和 dba_registry_sqlpatch 对不上?正常
这是最常让人困惑的点:opatch lsinventory 显示的是Oracle Home二进制层打了哪些补丁(比如29872031这种RU编号),而 dba_registry_sqlpatch 只反映这些补丁中“需要改数据字典”的那部分是否真正执行成功。两者根本不在一个层面,强行对比会得出错误结论。
常见错误现象:
- 刚用
opatch apply打完补丁,dba_registry_sqlpatch还是空的 → 忘了跑datapatch -
opatch lsinventory里有补丁ID,但dba_registry_sqlpatch里PATCH_ID字段显示为NULL→ 补丁不含SQL变更(例如纯OJVM JVM升级) - 同一条
PATCH_ID在dba_registry_sqlpatch出现两次,ACTION分别是APPLY和ROLLBACK→ 补丁被来回应用过,但字典状态以最后一次STATUS = 'SUCCESS'为准
想快速验证补丁是否生效?别只盯视图,看三处
光刷SQL语句容易漏掉关键信号。真正管用的检查是交叉比对三个地方,缺一不可:
-
opatch lspatches:确认二进制补丁已落地(输出应含目标补丁ID,如34567890) -
SELECT patch_id, status FROM dba_registry_sqlpatch WHERE action_time > SYSDATE-7:确认最近7天内SQL补丁执行成功(status必须是SUCCESS) -
SELECT version FROM v$version:看版本号第四位是否更新(例如从19.3.0.0.0升到19.22.0.0.0),这是RU/RUR完成的最终体现
如果这三项不一致,问题一定出在 datapatch 阶段——比如数据库没启到 UPGRADE 状态、或者 catbundle.sql 被跳过。
查补丁历史时最容易被忽略的权限和连接方式
dba_registry_sqlpatch 是DBA视图,但很多人用普通用户连上去查,结果返回空集或报错 ORA-00942: table or view does not exist。这不是视图不存在,是权限问题。
实操要点:
- 必须用
sqlplus / as sysdba或具有SELECT_CATALOG_ROLE的账户连接,普通DBA角色不一定够 - 不能连到PDB去查(除非明确指定容器):默认查的是当前容器,而补丁注册信息在CDB$ROOT里,要先
ALTER SESSION SET CONTAINER = CDB$ROOT - 如果数据库是RAC,
dba_registry_sqlpatch是全局视图,但opatch lsinventory必须逐节点执行——别在一个节点上查完就认为全集群都好了
补丁历史不是一次查询就能闭环的事,二进制、字典、版本号三者像齿轮咬合,少一个齿,整个升级状态就不可信。










