據(jù)庫季度補(bǔ)丁安裝全流程:從校驗(yàn)到datapatch固化)
簡(jiǎn)介針對(duì)Oracle數(shù)據(jù)庫11.2.0.3版Linux x86-64環(huán)境設(shè)計(jì)的補(bǔ)丁集更新包補(bǔ)丁編號(hào)20760997對(duì)應(yīng)PSU 11.2.0.3.15并集成2015年7月的關(guān)鍵補(bǔ)丁更新CPUJUL2015。這是數(shù)據(jù)庫管理員應(yīng)對(duì)安全漏洞與穩(wěn)定性問題的重要補(bǔ)丁適用于需長期維護(hù)且暫不升級(jí)大版本的11.2.0.3生產(chǎn)環(huán)境可緩解已知攻擊面并修正累積錯(cuò)誤。壓縮包約100.73MB含補(bǔ)丁程序及PatchSearch.xml說明文件后者提供補(bǔ)丁元數(shù)據(jù)、適用條件與依賴關(guān)系便于安裝前核對(duì)環(huán)境。已有290人學(xué)習(xí)下載。通過應(yīng)用該補(bǔ)丁DBA可熟悉Oracle補(bǔ)丁集更新與CPU落地流程及時(shí)為數(shù)據(jù)庫打上安全補(bǔ)丁提升系統(tǒng)防護(hù)水平保障業(yè)務(wù)連續(xù)性適合批量多實(shí)例維護(hù)與合規(guī)性運(yùn)維場(chǎng)景。1. 文件名拆解p20760997_112030_Linux-x86-64.zip 是 Oracle 的季度補(bǔ)丁包把p20760997_112030_Linux-x86-64.zip這個(gè)文件名扔給十個(gè)人九個(gè)會(huì)以為是普通軟件安裝包剩下一個(gè) DBA 會(huì)立刻警覺——這是 Oracle 數(shù)據(jù)庫的季度補(bǔ)丁包Quarterly Release Update。這類 zip 包解決的問題很直接你的數(shù)據(jù)庫可能正跑在某個(gè)已知 bug 上比如 SQL 執(zhí)行計(jì)劃突然變差、內(nèi)存泄漏、異常重啟而補(bǔ)丁包就是把修復(fù)后的二進(jìn)制文件和 SQL 腳本一次性打包交給你的交付物。適合誰看在 Linux x86-64 平臺(tái)上維護(hù) Oracle 11g/12c/19c 的運(yùn)維和 DBA尤其是收到補(bǔ)丁壓縮包卻不確定從哪一步開始的人。這篇文章不打算復(fù)述官方文檔而是按我實(shí)際打補(bǔ)丁的流程走一遍先識(shí)別這個(gè) zip 是什么、怎么解壓校驗(yàn)、打之前必須做什么、正式 apply 時(shí)的命令和參數(shù)、最容易翻車的地方以及打完怎么確認(rèn)真的生效。你可以把它當(dāng)成一份能照著抄的作業(yè)也可以用來排查已經(jīng)打了一半?yún)s卡住的現(xiàn)場(chǎng)。2. 裝前檢查把 zip 變成可安裝狀態(tài)的一整套校驗(yàn)補(bǔ)丁包以 zip 格式分發(fā)第一步自然是解壓但解壓之前有兩條信息比命令本身更重要這個(gè)補(bǔ)丁包的適用范圍和它的完整性。很多人一上來就unzip解壓到一半發(fā)現(xiàn)空間不夠或者打完opatch apply才發(fā)現(xiàn)補(bǔ)丁包是壞的白白折騰幾小時(shí)。2.1 先看補(bǔ)丁類型和適用范圍DB 補(bǔ)丁還是 GI 補(bǔ)丁p20760997_112030_Linux-x86-64.zip的命名規(guī)則是p補(bǔ)丁號(hào)_版本_平臺(tái).zip其中112030通常表示這屬于 11.2.0.3 或 11.2.0.4 系列的某個(gè)季度補(bǔ)丁包。在動(dòng)手之前先去補(bǔ)丁說明文檔里確認(rèn)三件事補(bǔ)丁類型是 Database RURelease Update還是 GI RUGrid Infrastructure。目標(biāo)環(huán)境是單機(jī)還是 RACRAC 的補(bǔ)丁流程和單機(jī)差異很大。補(bǔ)丁是否包含ojvm、DBWLM這類組件因?yàn)橛行┙M件需要單獨(dú)處理。我一般會(huì)把補(bǔ)丁說明文檔README下載到本地先看Post Install一節(jié)那里寫著打完后還需要執(zhí)行的 SQL 腳本或datapatch步驟。很多人以為opatch apply結(jié)束就萬事大吉實(shí)際上從 12.2 開始SQL 變更必須單獨(dú)固化README 里這一節(jié)漏掉的概率不低。2.2 Linux 下的 zip 解壓與校驗(yàn)md5sum 和 unzip 參數(shù)在 Linux 上解壓補(bǔ)丁包之前第一件事不是解壓而是校驗(yàn)文件完整性。MOS 文檔通常會(huì)給出這個(gè)文件的 SHA1 或 MD5 校驗(yàn)值用一條命令就能完成# 計(jì)算補(bǔ)丁包的 SHA1 校驗(yàn)值 sha1sum p20760997_112030_Linux-x86-64.zip # 如果文檔給的是 MD5用 md5sum 代替 md5sum p20760997_112030_Linux-x86-64.zip校驗(yàn)值對(duì)不上就重新下載否則后面opatch apply可能報(bào)Invalid patch archive或中途解壓失敗。接下來看壓縮包內(nèi)容確認(rèn)解壓后目錄大小避免解壓到一半撐爆磁盤# 列出補(bǔ)丁包內(nèi)所有文件看頂層目錄名稱 unzip -l p20760997_112030_Linux-x86-64.zip | head -30 # 查看 zip 包內(nèi)文件總大小預(yù)留雙倍空間更穩(wěn)妥 unzip -l p20760997_112030_Linux-x86-64.zip | tail -5確認(rèn)無誤后再正式解壓解壓時(shí)我習(xí)慣加-q靜默參數(shù)避免文件過多刷屏。補(bǔ)丁包解壓后通常是一個(gè)以補(bǔ)丁號(hào)命名的目錄比如20760997/里面是etc/、files/、README.txt這類標(biāo)準(zhǔn)結(jié)構(gòu)。# 靜默解壓到目標(biāo)目錄 unzip -q p20760997_112030_Linux-x86-64.zip -d /u01/app/oracle/patchdir/ # 解壓后看一眼目錄結(jié)構(gòu)確認(rèn)沒有解壓失敗留下的殘缺文件 ls -l /u01/app/oracle/patchdir/20760997/這里有一個(gè)很容易被忽略的細(xì)節(jié)解壓之后目錄里的文件屬主和權(quán)限可能不是你預(yù)期的樣子。如果你是用 root 解壓的后續(xù)用 oracle 用戶跑opatch時(shí)會(huì)遇到權(quán)限問題。常見做法是解壓完成后直接 chown 給 oracle 用戶或者干脆全程用 oracle 用戶解壓。我自己的習(xí)慣是unzip這一步就用 oracle 身份執(zhí)行省得后面還要改屬主。提示解壓前養(yǎng)成看README.txt的習(xí)慣里面有Prerequisite一節(jié)寫著 OPatch 最低版本要求。這一節(jié)沒看后面 90% 會(huì)在opatch apply時(shí)報(bào) OPatch 版本不夠。2.3 檢查 ORACLE_HOME、OPatch 版本與磁盤空間補(bǔ)丁包解壓好只是準(zhǔn)備工作的一部分更關(guān)鍵的是確認(rèn)目標(biāo)環(huán)境滿足前提條件。我用一套固定命令完成檢查# 確認(rèn) ORACLE_HOME 路徑避免打錯(cuò)環(huán)境 echo $ORACLE_HOME # 查看當(dāng)前 OPatch 版本 $ORACLE_HOME/OPatch/opatch version # 檢查關(guān)鍵目錄磁盤空間預(yù)留補(bǔ)丁體積的兩倍以上 df -h /u01 /u02OPatch 版本檢查尤其重要。每個(gè)補(bǔ)丁包的 README 里都會(huì)寫明最低 OPatch 版本要求比如要求11.2.0.3.28以上。如果現(xiàn)有版本低于要求需要先單獨(dú)下載對(duì)應(yīng)版本的 OPatch 包MOS 文檔 6880880覆蓋到$ORACLE_HOME/OPatch目錄。磁盤空間方面補(bǔ)丁包解壓后的目錄大小是其一opatch apply過程中還會(huì)在$ORACLE_HOME/.patch_storage生成備份這部分空間常常被人忘掉。我見過幾次打補(bǔ)丁打到一半報(bào)表空間不足失敗的最后只能清理臨時(shí)文件再從頭來。穩(wěn)妥的做法是預(yù)留解壓后補(bǔ)丁體積兩倍以上的空間同時(shí)確認(rèn)$ORACLE_HOME所在掛載點(diǎn)剩余空間充足。3. 停庫與備份打補(bǔ)丁之前必須做的事補(bǔ)丁包解壓完成、環(huán)境檢查通過接下來不是直接opatch apply而是把數(shù)據(jù)庫停干凈、把備份做好。這一步很多人覺得浪費(fèi)時(shí)間但補(bǔ)丁一旦打壞回滾的成本遠(yuǎn)高于這半小時(shí)的備份時(shí)間。3.1 干凈的關(guān)閉數(shù)據(jù)庫為什么必須 shutdown immediate打補(bǔ)丁時(shí)數(shù)據(jù)庫進(jìn)程還在運(yùn)行oracle 二進(jìn)制文件正被進(jìn)程占用opatch根本無法替換文件。即便能替換運(yùn)行中的進(jìn)程持有舊版本的內(nèi)存結(jié)構(gòu)打完補(bǔ)丁后新舊代碼混在一起崩潰是遲早的事。因此必須先關(guān)閉數(shù)據(jù)庫實(shí)例和監(jiān)聽。-- 以 sysdba 身份連接數(shù)據(jù)庫并關(guān)閉實(shí)例 sqlplus / as sysdba SQL shutdown immediate; SQL exit;shutdown immediate會(huì)等待當(dāng)前事務(wù)回滾并中斷連接通常幾十秒內(nèi)完成。如果數(shù)據(jù)庫里有大量未提交的長事務(wù)可能會(huì)卡住這時(shí)可以檢查v$session里有哪些活動(dòng)會(huì)話。RAC 環(huán)境則要用srvctl stop database -d dbname停掉所有實(shí)例并確認(rèn)所有節(jié)點(diǎn)上的監(jiān)聽進(jìn)程都已經(jīng)停止。# 停掉監(jiān)聽避免新連接嘗試進(jìn)入數(shù)據(jù)庫 lsnrctl stop # RAC 環(huán)境用 srvctl 停止數(shù)據(jù)庫和監(jiān)聽 srvctl stop listener -n $(hostname)還有一個(gè)容易漏掉的地方11g 以后的$ORACLE_HOME如果是 GI 環(huán)境crsctl stat resource里可能還有ora.ons、ora.evmd這類進(jìn)程在跑。這些進(jìn)程不持鎖但保險(xiǎn)起見單機(jī)環(huán)境我一般只停實(shí)例、監(jiān)聽和 ASM 實(shí)例即可不用把整個(gè) GI 棧都停掉。3.2 備份策略冷備份目錄還是 RMAN 備份打補(bǔ)丁會(huì)替換$ORACLE_HOME下的二進(jìn)制文件所以備份的核心是ORACLE_HOME目錄本身而不是數(shù)據(jù)文件。不過在打補(bǔ)丁期間數(shù)據(jù)庫處于關(guān)閉狀態(tài)利用這個(gè)空窗做一次冷備或 RMAN 全備能把風(fēng)險(xiǎn)壓到最低。# 冷備份把 ORACLE_HOME 整體復(fù)制一份速度慢但對(duì)回滾最直接 cp -rp $ORACLE_HOME /u01/backup/ORACLE_HOME_$(date %Y%m%d) # 如果數(shù)據(jù)庫不大順手把數(shù)據(jù)目錄也冷備一份 cp -rp $ORACLE_DATA /u01/backup/ORACLE_DATA_$(date %Y%m%d)我一般用cp -rp保留屬主和權(quán)限備份完之后用du -sh確認(rèn)備份體積正常避免復(fù)制過程中文件缺失。如果數(shù)據(jù)庫走的是歸檔模式也可以只做 RMAN 增量備份但打補(bǔ)丁期間數(shù)據(jù)文件不會(huì)變化冷備份的性價(jià)比更高。注意cp -rp備份的是一個(gè)可用的 ORACLE_HOME。如果備份出來的目錄缺了lib/下某個(gè)共享庫回滾時(shí)可能直接報(bào)cannot restore所以備份完之后最好ls -l $ORACLE_HOME/bin/oracle確認(rèn)主程序文件存在。3.3 OPatch 版本不夠時(shí)怎么替換p6880880 的覆蓋步驟如果第 2 章檢查發(fā)現(xiàn) OPatch 版本低于補(bǔ)丁要求需要先升級(jí) OPatch。常見做法是下載p6880880_版本_平臺(tái).zip然后覆蓋$ORACLE_HOME/OPatch目錄。# 備份現(xiàn)有 OPatch萬一新版有問題可以立即回退 mv $ORACLE_HOME/OPatch $ORACLE_HOME/OPatch_bak_$(date %Y%m%d) # 解壓新版 OPatch 并確認(rèn)版本號(hào) unzip -q p6880880_112000_Linux-x86-64.zip -d /tmp/opatch_new/ mv /tmp/opatch_new/OPatch $ORACLE_HOME/ # 確認(rèn)新版本生效 $ORACLE_HOME/OPatch/opatch version替換 OPatch 時(shí)有一個(gè)細(xì)節(jié)OPatch目錄下有opatch可執(zhí)行文件、doc/、bin/等子目錄覆蓋時(shí)要保持目錄結(jié)構(gòu)完整。另外如果$ORACLE_HOME/OPatch里已經(jīng)有之前打補(bǔ)丁留下的.backup文件老版本 OPatch 的備份信息可能會(huì)失效。所以替換 OPatch 之前確保當(dāng)前沒有處于半打補(bǔ)丁狀態(tài)否則新版 OPatch 無法識(shí)別舊的中間狀態(tài)后續(xù)opatch rollback也會(huì)失敗。4. 正式打補(bǔ)丁從 opatch apply 到 SQL 固化準(zhǔn)備工作全部完成進(jìn)入主流程。這一章按順序拆成三個(gè)步驟預(yù)檢查、正式 apply、SQL 層固化。很多人只做第二步忽略了第一步和第三步結(jié)果補(bǔ)丁狀態(tài)顯示成功實(shí)際 SQL 變更沒有生效。4.1 opatch apply -prereq 預(yù)檢查先試運(yùn)行一次正式應(yīng)用補(bǔ)丁前我強(qiáng)烈建議先跑一次預(yù)檢查。opatch apply命令自帶-prereq參數(shù)只做環(huán)境驗(yàn)證和沖突檢測(cè)不會(huì)實(shí)際修改任何文件。這一步能把大部分風(fēng)險(xiǎn)提前暴露出來避免正式 apply 到一半失敗。# 進(jìn)入補(bǔ)丁目錄先做預(yù)檢查 cd /u01/app/oracle/patchdir/20760997 # 以 oracle 用戶執(zhí)行預(yù)檢查 $ORACLE_HOME/OPatch/opatch apply -prereq -invPtrLoc $ORACLE_HOME/oraInst.loc-invPtrLoc用于指定 inventory 指針文件的位置。單機(jī)環(huán)境如果不加這個(gè)參數(shù)opatch 可能找不到 inventory 而直接報(bào)錯(cuò)。預(yù)檢查輸出里重點(diǎn)看兩個(gè)部分Prerequisite Checks是否全部為SUCCESS以及Conflicting Patches是否為空。如果有沖突比如之前打過某個(gè) interim patch這次 RU 會(huì)拒絕安裝需要先回滾那個(gè)小補(bǔ)丁。預(yù)檢查通過后再執(zhí)行正式 apply# 正式應(yīng)用補(bǔ)丁記錄完整日志以便排錯(cuò) $ORACLE_HOME/OPatch/opatch apply -invPtrLoc $ORACLE_HOME/oraInst.loc 21 | tee /tmp/opatch_apply_$(date %Y%m%d).logtee會(huì)把輸出同時(shí)打到屏幕和日志文件遇到失敗時(shí)可以回頭翻日志。apply 過程中如果卡住不動(dòng)最常見的原因是磁盤空間不足或某個(gè)文件被進(jìn)程占用。日志文件里有Error關(guān)鍵字時(shí)用grep -i error快速定位# 查看 apply 日志中是否有報(bào)錯(cuò) grep -i error /tmp/opatch_apply_*.log正常完成時(shí)opatch 會(huì)輸出OPatch succeeded。此時(shí)補(bǔ)丁已經(jīng)替換了$ORACLE_HOME下的二進(jìn)制文件但數(shù)據(jù)庫還沒有啟動(dòng)SQL 層的變更也還沒有應(yīng)用。4.2 啟動(dòng)數(shù)據(jù)庫并執(zhí)行 datapatchSQL 固化步驟從 12.2 開始RU 補(bǔ)丁里同時(shí)包含二進(jìn)制修復(fù)和 SQL 變更。二進(jìn)制部分由opatch apply完成SQL 部分必須用datapatch工具單獨(dú)執(zhí)行。如果漏掉這一步DBA_REGISTRY_SQLPATCH里不會(huì)記錄新的補(bǔ)丁信息即使opatch lsinventory顯示補(bǔ)丁已安裝實(shí)際 SQL 變更也沒生效。# 啟動(dòng)數(shù)據(jù)庫到正常模式 sqlplus / as sysdba SQL startup; SQL alter pluggable database all open; SQL exit; # 執(zhí)行 SQL 固化-verbose 輸出詳細(xì)過程 cd $ORACLE_HOME/OPatch ./datapatch -verbose 21 | tee /tmp/datapatch_$(date %Y%m%d).logdatapatch會(huì)自動(dòng)檢測(cè)需要應(yīng)用和回滾的 SQL 補(bǔ)丁并生成對(duì)應(yīng)的日志文件。執(zhí)行過程中如果某個(gè) PDB 沒有打開會(huì)跳過并給出警告。我遇到過幾次datapatch報(bào)錯(cuò)原因是某個(gè) PDB 處于 restricted 模式或 mount 狀態(tài)正常打開后重新執(zhí)行即可。# 查看 datapatch 日志確認(rèn)所有 PDB 都已成功 grep -E Patching|ERROR|FAILED /tmp/datapatch_*.logdatapatch完成之后補(bǔ)丁的 SQL 層才真正生效。11.2.0.4 之前的版本沒有datapatch需要手動(dòng)執(zhí)行$ORACLE_HOME/rdbms/admin/catbundle.sql這類腳本但那是另一個(gè)話題。11.2.0.4 的季度補(bǔ)丁包里SQL 變更一般通過catbundle_opatch.sql執(zhí)行具體以 README 的Post Install為準(zhǔn)。4.3 補(bǔ)丁狀態(tài)的最終確認(rèn)opatch lsinventoryapply 和 datapatch 都完成之后還要做一次狀態(tài)確認(rèn)確保補(bǔ)丁記錄完整。# 列出當(dāng)前 ORACLE_HOME 中所有已安裝的補(bǔ)丁 $ORACLE_HOME/OPatch/opatch lsinventory -invPtrLoc $ORACLE_HOME/oraInst.loc 21 | tee /tmp/lsinventory_$(date %Y%m%d).log # 過濾出本次補(bǔ)丁號(hào) grep -A2 20760997 /tmp/lsinventory_*.log輸出中補(bǔ)丁狀態(tài)顯示為APPLIED說明二進(jìn)制層面已成功。SQL 層面的確認(rèn)需要查數(shù)據(jù)字典-- 確認(rèn) SQL 補(bǔ)丁狀態(tài) SELECT patch_id, patch_uid, status, action, time FROM dba_registry_sqlpatch;status為SUCCESSaction為APPLYpatch_id是 20760997就說明整個(gè)補(bǔ)丁鏈路完整。這里有一個(gè)坑opatch lsinventory顯示APPLIED但dba_registry_sqlpatch里查不到記錄多半是datapatch沒有執(zhí)行或執(zhí)行失敗被忽略了。兩個(gè)命令的輸出要同時(shí)核對(duì)才算真正打完。5. 打補(bǔ)丁前后最需要注意的 5 個(gè)雷區(qū)補(bǔ)丁包本身沒問題安裝流程也是標(biāo)準(zhǔn)操作但實(shí)際執(zhí)行時(shí)總會(huì)在一些細(xì)節(jié)上翻車。這里列出我踩過和別人踩過最多的 5 個(gè)問題按“現(xiàn)象 → 原因 → 解決”順序?qū)憽?.1 校驗(yàn)和不一致補(bǔ)丁包是壞的解壓看起來卻很正?,F(xiàn)象unzip -l能正常列出文件unzip -q解壓也成功但opatch apply -prereq時(shí)報(bào)Invalid patch archive或Patch archive is corrupt。原因zip 包內(nèi)部某個(gè)文件在下載過程中損壞但 zip 目錄結(jié)構(gòu)完整。僅靠unzip -t檢測(cè)不出這類問題因?yàn)閡nzip -t只檢查 CRC而損壞發(fā)生在文件內(nèi)容層面CRC 不一定重新計(jì)算。解決不要繼續(xù)嘗試 apply用sha1sum和官方提供的校驗(yàn)值對(duì)比不一致就重新下載。另外解壓時(shí)用-t做一次完整測(cè)試能提前發(fā)現(xiàn)大部分問題# 解壓前做完整測(cè)試有問題會(huì)明確報(bào)錯(cuò) unzip -t p20760997_112030_Linux-x86-64.zip | tail -105.2 OPatch 版本過低apply 在第一個(gè)檢查項(xiàng)就中斷現(xiàn)象opatch apply -prereq報(bào)OPatch version ... is below required version直接退出。原因READM 的前置條件里寫明了 OPatch 版本要求但準(zhǔn)備階段沒檢查或檢查了沒執(zhí)行。解決按第 3 章的流程替換 OPatch。替換后再次確認(rèn)版本號(hào)然后重新跑opatch apply -prereq。注意替換 OPatch 時(shí)不能損壞.backup結(jié)構(gòu)否則舊補(bǔ)丁信息會(huì)丟失后續(xù) rollback 會(huì)失敗。5.3 數(shù)據(jù)庫沒停干凈apply 報(bào)文件正在使用現(xiàn)象opatch apply執(zhí)行到一半報(bào)libserver.so或oracle文件被占用apply 失敗。原因?qū)嵗_實(shí)shutdown immediate了但監(jiān)聽進(jìn)程、ASM 實(shí)例或遺留的sqlplus會(huì)話還持有$ORACLE_HOME下文件的句柄。Linux 下文件被占用opatch 無法覆蓋。解決先停監(jiān)聽確認(rèn) ASM 實(shí)例狀態(tài)再檢查是否有殘留的 oracle 進(jìn)程# 確認(rèn)所有 oracle 相關(guān)進(jìn)程都已退出 ps -ef | grep -E pmon|smon|lsnr|asm | grep -v grep如果還有進(jìn)程殘留用kill殺掉失控進(jìn)程但要注意區(qū)分正常后臺(tái)進(jìn)程千萬不要誤殺crsd或ohasd。5.4 磁盤空間不足apply 到 80% 時(shí) Backup 目錄寫入失敗現(xiàn)象opatch apply輸出Unable to create backup file或直接報(bào)space相關(guān)錯(cuò)誤。原因apply 過程中會(huì)在$ORACLE_HOME/.patch_storage里備份被替換的舊文件備份體積可能接近補(bǔ)丁包本身大小。規(guī)劃空間時(shí)只算了補(bǔ)丁解壓后的體積漏掉了這個(gè)備份目錄。解決打補(bǔ)丁前df -h確認(rèn)$ORACLE_HOME所在掛載點(diǎn)剩余空間預(yù)留補(bǔ)丁體積的兩倍以上。如果空間不夠清理$ORACLE_HOME/.patch_storage下的歷史備份# 查看歷史備份占用的空間 du -sh $ORACLE_HOME/.patch_storage/* # 清理不需要的舊補(bǔ)丁備份注意保留當(dāng)前的 rm -rf $ORACLE_HOME/.patch_storage/舊補(bǔ)丁目錄*5.5 datapatch 被忽略補(bǔ)丁顯示 APPLIED 但 SQL 沒變現(xiàn)象opatch lsinventory顯示補(bǔ)丁APPLIED但應(yīng)用代碼反饋性能問題和之前一樣查dba_registry_sqlpatch沒有對(duì)應(yīng)記錄。原因省略了第 4.2 節(jié)的datapatch步驟或者執(zhí)行了但沒看輸出某個(gè) PDB 沒打開導(dǎo)致 SQL 變更沒應(yīng)用。解決啟動(dòng)數(shù)據(jù)庫并打開所有 PDB 后重新執(zhí)行datapatch -verbose執(zhí)行完用SELECT * FROM dba_registry_sqlpatch驗(yàn)證。如果datapatch報(bào)錯(cuò)查看$ORACLE_HOME/OPatch/datapatch日志目錄下的.log文件定位具體失敗點(diǎn)修復(fù)后重新執(zhí)行即可。6. 驗(yàn)證補(bǔ)丁真正生效數(shù)據(jù)字典查詢、回滾方案與日常習(xí)慣補(bǔ)丁打完不代表工作結(jié)束最后一關(guān)是驗(yàn)證和備案。這一章說三個(gè)動(dòng)作查數(shù)據(jù)字典確認(rèn) SQL 變更、準(zhǔn)備好回滾方案、把補(bǔ)丁信息存檔。先查 SQL 補(bǔ)丁狀態(tài)。用 SQL*Plus 執(zhí)行以下查詢確認(rèn)20760997的狀態(tài)為SUCCESSSET LINESIZE 200 COL status FORMAT A12 COL action FORMAT A12 COL patch_id FORMAT 99999999 SELECT patch_id, patch_uid, status, action, TO_CHAR(time, YYYY-MM-DD HH24:MI) AS apply_time FROM dba_registry_sqlpatch ORDER BY time DESC;輸出里有20760997且statusSUCCESS說明 SQL 層已經(jīng)生效。同時(shí)再跑一次opatch lsinventory確認(rèn)二進(jìn)制層和應(yīng)用層都一致。兩個(gè)結(jié)果都正常這個(gè)補(bǔ)丁才算真正打完了?;貪L方案按順序備案。RU 補(bǔ)丁大多可以被opatch rollback回退但前提是.patch_storage里的備份沒有被清理。執(zhí)行前先確認(rèn)可回滾性# 查詢補(bǔ)丁是否支持回滾 $ORACLE_HOME/OPatch/opatch rollback -query 20760997如果輸出顯示可回滾回滾命令是opatch rollback -id 20760997?;貪L后同樣需要重新跑datapatch -rollback來回退 SQL 變更。不過實(shí)際生產(chǎn)中補(bǔ)丁一旦 APPLY 成功且跑了一段時(shí)間我更傾向于不回滾而是打下一個(gè)修正補(bǔ)丁因?yàn)榛貪L可能引入新的兼容性問題。補(bǔ)丁信息存檔是我個(gè)人的習(xí)慣。打完補(bǔ)丁后把以下信息記錄到補(bǔ)丁目錄下的一個(gè)文本文件里補(bǔ)丁號(hào)、平臺(tái)、數(shù)據(jù)庫版本、OPatch 版本、apply 時(shí)間、lsinventory的輸出快照、datapatch日志路徑。下次打補(bǔ)丁前拿出來對(duì)比能快速確認(rèn)環(huán)境是否干凈。# 記錄補(bǔ)丁信息到存檔文件方便下次運(yùn)維直接引用 echo $(date) /u01/app/oracle/patchdir/patch_log.txt $ORACLE_HOME/OPatch/opatch lsinventory -invPtrLoc $ORACLE_HOME/oraInst.loc /u01/app/oracle/patchdir/patch_log.txt這套習(xí)慣幫我避免過不少麻煩。有一次環(huán)境里有多套 ORACLE_HOME補(bǔ)丁打到了錯(cuò)誤的目錄靠的就是存檔里的lsinventory快照對(duì)比才定位出來。希望幫你省下同樣的時(shí)間。本文還有配套的精品資源點(diǎn)擊獲取