丁應(yīng)用實(shí)戰(zhàn):Opatch工具避坑指南)
簡(jiǎn)介面向 Windows 平臺(tái) Oracle 12c 運(yùn)維人員這套 Opatch 補(bǔ)丁工具包用于解決補(bǔ)丁安裝與維護(hù)過(guò)程中必需的補(bǔ)丁管理環(huán)境缺失問(wèn)題使數(shù)據(jù)庫(kù)補(bǔ)丁、PSU 及 CPU 更新能夠順利執(zhí)行。壓縮包共含 454 個(gè)文件、約 102.88MB以 jar 核心庫(kù)、dll 動(dòng)態(tài)鏈接文件、exe 可執(zhí)行程序、bat 與 cmd 腳本、properties 配置文件為主體同時(shí)提供 md 說(shuō)明文檔、txt 指引、sh 輔助腳本等覆蓋工具運(yùn)行、環(huán)境配置與問(wèn)題排查所需的關(guān)鍵組件。資源已吸引 996 人學(xué)習(xí)下載適用于需要在 Windows 環(huán)境獨(dú)立維護(hù) Oracle 12c、準(zhǔn)備應(yīng)用季度補(bǔ)丁或修復(fù) Opatch 工具異常的 DBA 與系統(tǒng)工程師。借助整理好的目錄結(jié)構(gòu)與現(xiàn)成文件可快速完成補(bǔ)丁環(huán)境部署減少自行收集和配置組件的時(shí)間成本同時(shí)在升級(jí)前做好預(yù)檢與備份降低補(bǔ)丁失敗風(fēng)險(xiǎn)。1. 為什么Windows上的Oracle 12c補(bǔ)丁總是讓人頭疼在Windows服務(wù)器上維護(hù)Oracle 12c的DBA大都經(jīng)歷過(guò)這種場(chǎng)面補(bǔ)丁包從MOS下載好了解壓到服務(wù)器雙擊setup.exe結(jié)果報(bào)一個(gè)看不懂的錯(cuò)或者明明提示補(bǔ)丁應(yīng)用成功重啟數(shù)據(jù)庫(kù)后查版本號(hào)卻什么都沒(méi)變。問(wèn)題八成出在Opatch這個(gè)環(huán)節(jié)上。window oracle12c補(bǔ)丁Opatch這件事說(shuō)白了就是兩件事先把Opatch工具本身搞對(duì)再用它把補(bǔ)丁正確灌進(jìn)Oracle 12c的安裝目錄。聽(tīng)起來(lái)簡(jiǎn)單但Windows沒(méi)有Linux那種root權(quán)限和清晰的文件系統(tǒng)布局路徑、權(quán)限、服務(wù)狀態(tài)里的任何一個(gè)坑都能讓補(bǔ)丁無(wú)聲失敗。這篇文把從下載、檢查、打補(bǔ)丁到驗(yàn)證回滾的完整路徑拆開(kāi)講適合正在Windows上維護(hù)Oracle 12c單機(jī)或RAC的運(yùn)維、DBA以及剛接手Oracle環(huán)境、需要在測(cè)試庫(kù)上練手的開(kāi)發(fā)人員。先給結(jié)論Windows上打12c補(bǔ)丁90%的失敗跟補(bǔ)丁本身無(wú)關(guān)跟環(huán)境準(zhǔn)備有關(guān)。2. 認(rèn)識(shí)Opatch與12c補(bǔ)丁機(jī)制為什么Windows上要先看readme再動(dòng)手2.1 先搞清楚三件事ORACLE_HOME、Opatch版本、補(bǔ)丁類(lèi)型Opatch是Oracle官方提供的補(bǔ)丁管理工具它的作用可以理解成給Oracle軟件目錄做版本管理和文件替換的“安裝器plus”。它不直接改數(shù)據(jù)庫(kù)里的數(shù)據(jù)而是把補(bǔ)丁中的文件復(fù)制到ORACLE_HOME同時(shí)更新inventory記錄——Oracle靠這份記錄知道當(dāng)前裝了哪些補(bǔ)丁下次再打補(bǔ)丁時(shí)判斷沖突和依賴(lài)。Windows上我們面對(duì)的路徑一般來(lái)說(shuō)是這種形態(tài)C:\app\oracle\product\12.2.0\dbhome_1這個(gè)等號(hào)后面的目錄就是ORACLE_HOME。Opatch本體就在ORACLE_HOME的OPatch子目錄下文件名是opatch.bat。注意Windows下沒(méi)有opatch直接敲opatch會(huì)提示不是內(nèi)部或外部命令必須用opatch.bat或者先進(jìn)入OPatch目錄再執(zhí)行。補(bǔ)丁類(lèi)型要分清。12c時(shí)代最常見(jiàn)的三類(lèi)PSUPatch Set Update季度累積補(bǔ)丁包含安全修復(fù)和關(guān)鍵修復(fù)數(shù)據(jù)庫(kù)和客戶(hù)端各有一套文件名類(lèi)似p12345678_122010_MSWIN-x86-64.zip。OJVM補(bǔ)丁針對(duì)Java虛擬機(jī)組件的補(bǔ)丁獨(dú)立于PSU文件名常帶OJVM字樣。一次性修復(fù)補(bǔ)丁One-off針對(duì)單個(gè)Bug文件名不規(guī)律依賴(lài)關(guān)系需要額外查MOS文檔。這三類(lèi)補(bǔ)丁的Opatch前置版本要求不一樣具體每個(gè)補(bǔ)丁包的readme.html里都寫(xiě)了。不要跳讀Windows下環(huán)境檢查比Linux更敏感跳過(guò)一步后面翻車(chē)的概率很大。2.2 Windows和Linux打補(bǔ)丁的本質(zhì)差異把Oracle裝在Windows上的人基本是兩種原因一是開(kāi)發(fā)測(cè)試環(huán)境沒(méi)必要上Linux二是業(yè)務(wù)系統(tǒng)本身跑在Windows生態(tài)里。無(wú)論哪種打補(bǔ)丁的思路和Linux很不一樣硬套Linux經(jīng)驗(yàn)會(huì)出事。第一權(quán)限模型不同。Linux下用oracle用戶(hù)執(zhí)行opatch講究的是文件屬主Windows下沒(méi)有真正意義上的“以oracle用戶(hù)身份運(yùn)行”只有管理員權(quán)限。Windows Vista之后有UAC右鍵“以管理員身份運(yùn)行”開(kāi)的cmd窗口和普通cmd窗口看到的環(huán)境變量、可寫(xiě)目錄不同。Opatch需要寫(xiě)ORACLE_HOME里十幾個(gè)子目錄還要讀注冊(cè)表里Oracle的inventory信息普通權(quán)限的cmd跑opatch apply大概率報(bào)權(quán)限不足。第二服務(wù)管理方式不同。Linux下用sqlplus / as sysdba啟動(dòng)關(guān)閉實(shí)例Windows下Oracle是以Windows服務(wù)的形式存在服務(wù)名叫OracleServiceORCLORCL是實(shí)例名。打補(bǔ)丁前需要把這個(gè)服務(wù)停掉但有幾個(gè)服務(wù)不能停OracleOraDB12Home1MTSRecoveryService和OracleOraDB12Home1TNSListener這類(lèi)監(jiān)聽(tīng)和恢復(fù)服務(wù)停了起不來(lái)會(huì)更麻煩。正確的做法是看readme大部分?jǐn)?shù)據(jù)庫(kù)補(bǔ)丁要求只停數(shù)據(jù)庫(kù)實(shí)例服務(wù)不要求停監(jiān)聽(tīng)。第三路徑寫(xiě)成什么樣有講究。Windows路徑不區(qū)分大小寫(xiě)但Opatch在解析路徑時(shí)用的是JavaJava對(duì)路徑分隔符的容忍度有限。用反斜杠\或者直接復(fù)制Windows路徑粘貼進(jìn)cmd在一些老的12c補(bǔ)丁版本上會(huì)報(bào)Invalid path。我一般統(tǒng)一用正斜杠或反斜杠都行關(guān)鍵是路徑里不能有空格——這是個(gè)大坑后面專(zhuān)門(mén)寫(xiě)。第四環(huán)境變量傳遞方式不同。Linux下.bash_profile里設(shè)置的ORACLE_HOME在ssh進(jìn)去時(shí)已經(jīng)生效Windows下cmd窗口里的ORACLE_HOME要么注冊(cè)表里有、要么不存在。Opatch不愿意用注冊(cè)表里的ORACLE_HOME它優(yōu)先讀當(dāng)前cmd環(huán)境變量所以每次新開(kāi)cmd窗口第一件事是set ORACLE_HOME...哪怕剛才那個(gè)窗口已經(jīng)設(shè)過(guò)。2.3 動(dòng)手前必須執(zhí)行的三個(gè)檢查命令打補(bǔ)丁前先把環(huán)境摸清楚。下面的操作以管理員身份運(yùn)行cmd依次執(zhí)行。set ORACLE_HOMEC:\app\oracle\product\12.2.0\dbhome_1 cd /d %ORACLE_HOME%\OPatch opatch.bat version opatch.bat lsinventory -details -oh %ORACLE_HOME%第一行設(shè)置環(huán)境變量后面命令里的%ORACLE_HOME%全部依賴(lài)這行。opatch.bat version檢查Opatch工具版本需要高于補(bǔ)丁readme里要求的最低版本否則后面apply時(shí)會(huì)被攔下來(lái)報(bào)OPatch version must be ...。opatch.bat lsinventory -details列出當(dāng)前home里已裝的補(bǔ)丁輸出結(jié)果很長(zhǎng)重點(diǎn)看最后一段的List of Oracle Homes和已安裝補(bǔ)丁列表確認(rèn)沒(méi)有之前殘留的半截補(bǔ)丁——?dú)埩粞a(bǔ)丁會(huì)讓新補(bǔ)丁的依賴(lài)檢查直接失敗。第三個(gè)檢查命令不是必須在cmd里跑的但Windows環(huán)境強(qiáng)烈建議做一遍用注冊(cè)表編輯器確認(rèn)ORACLE_HOME的值和你的認(rèn)知一致。WinR輸入regedit進(jìn)入HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\KEY_OraDB12Home1看ORACLE_HOME和ORACLE_BASE兩個(gè)字符串值。有些服務(wù)器以前重裝過(guò)Oracle注冊(cè)表里留下舊路徑Opatch讀注冊(cè)表信息時(shí)就取到了錯(cuò)誤的家目錄。還要順手確認(rèn)C:\Program Files\Oracle\Inventory存在這是Oracle中央inventoryopatch要往里面寫(xiě)操作記錄。提示以上三條命令輸出分別對(duì)應(yīng)“Opatch工具版本是否夠新”“現(xiàn)有補(bǔ)丁環(huán)境是否干凈”“ORACLE_HOME路徑是否被注冊(cè)表誤導(dǎo)”任何一步輸出和預(yù)期不符都要先解決不要帶到下一步。3. 在Windows上實(shí)際打一個(gè)12c補(bǔ)丁從下載到apply3.1 下載并準(zhǔn)備補(bǔ)丁包注意zip解壓路徑不能帶空格補(bǔ)丁包從My Oracle SupportMOS下載登錄后按補(bǔ)丁號(hào)搜索。以12.2.0.1的Windows x86-64平臺(tái)為例下載到的文件一般叫p29342341_122010_MSWIN-x86-64.zip這樣的形式。中間的122010代表12.2.0.1.0MSWIN指微軟Windows平臺(tái)。注意不要下成Linux版Windows和Linux的補(bǔ)丁文件不能混用。解壓這一步是第一個(gè)容易翻車(chē)的地方。解壓目標(biāo)路徑不能有空格尤其不要直接解壓到C:\Program Files或桌面用戶(hù)名里有中文的情況也很常見(jiàn)。Windows的Java虛擬機(jī)在解析帶空格的路徑時(shí)大概率出現(xiàn)cannot find the file或Exception in thread main。我一般固定解壓到C:\temp\opatch\下目錄層級(jí)保持簡(jiǎn)單比如mkdir C:\temp\opatch cd /d C:\temp\opatch rem 假設(shè)zip已放在C:\temp\opatch下 tar -xf p29342341_122010_MSWIN-x86-64.ziptar是Windows 10 1803之后系統(tǒng)自帶的工具如果沒(méi)有就用WinRAR或7-Zip注意選擇“解壓到當(dāng)前文件夾”不要生成嵌套的帶空格長(zhǎng)目錄。解壓后確認(rèn)目錄里有README.txt或readme.html——很多補(bǔ)丁包里還有bundle.xml、PatchSearch.xml這些元數(shù)據(jù)文件說(shuō)明解壓完整。如果只解壓出來(lái)一個(gè)空目錄說(shuō)明zip沒(méi)有完整下載重新下載。3.2 升級(jí)Opatch工具本身先打工具補(bǔ)丁再打數(shù)據(jù)庫(kù)補(bǔ)丁檢查完環(huán)境接著要確認(rèn)一件事當(dāng)前Opatch版本是否滿(mǎn)足補(bǔ)丁的最低要求。用第2章的命令查出來(lái)是一串像12.2.0.1.x的數(shù)字對(duì)比readme里OPatch Version一欄。如果不夠需要單獨(dú)從MOS下載Opatch工具補(bǔ)丁比如p6880880_122010_MSWIN-x86-64.zip。升級(jí)Opatch工具的步驟本質(zhì)就是用新版的opatch.bat等文件覆蓋舊版。操作方式是下載工具zip、解壓后得到OPatch目錄把這個(gè)新目錄整體復(fù)制到ORACLE_HOME下直接覆蓋原OPatch目錄。這一步不通過(guò)opatch命令執(zhí)行就是文件替換。替換前建議把舊OPatch目錄改名備份比如cd /d %ORACLE_HOME% ren OPatch OPatch_bak_20240101 rem 將解壓出來(lái)的新OPatch目錄復(fù)制到此處 xcopy /E /I /Q C:\temp\opatch\OPatch %ORACLE_HOME%\OPatch參數(shù)說(shuō)明/E復(fù)制所有子目錄包括空目錄/I如果目標(biāo)目錄不存在則自動(dòng)創(chuàng)建/Q靜默模式不展示每個(gè)文件的復(fù)制信息。之后再次執(zhí)行opatch.bat version確認(rèn)版本號(hào)已提升。這里有個(gè)容易忽略的細(xì)節(jié)如果服務(wù)器上同時(shí)裝了Oracle客戶(hù)端和數(shù)據(jù)庫(kù)兩個(gè)HOME需要分別更新各自的Opatch且先更新哪一個(gè)不影響但每個(gè)HOME的補(bǔ)丁都要用自己的Opatch打。注意Opatch工具升級(jí)本質(zhì)上是用新版文件覆蓋老版本。覆蓋后原本已經(jīng)應(yīng)用過(guò)的補(bǔ)丁記錄仍然保留在inventory里不會(huì)丟失。但如果inventory本身?yè)p壞覆蓋Opatch目錄不能解決要另外用opatch lsinventory檢查中央inventory的可用性。3.3 opatch apply詳細(xì)過(guò)程和參數(shù)工具版本已滿(mǎn)足之后開(kāi)始應(yīng)用補(bǔ)丁。以一次性補(bǔ)丁為例步驟是進(jìn)入解壓目錄、確認(rèn)補(bǔ)丁號(hào)、執(zhí)行apply。完整命令序列如下。set ORACLE_HOMEC:\app\oracle\product\12.2.0\dbhome_1 cd /d C:\temp\opatch\29342341 %ORACLE_HOME%\OPatch\opatch.bat apply -oh %ORACLE_HOME%apply是主命令后跟補(bǔ)丁目錄路徑含義是“把當(dāng)前目錄解讀為一個(gè)補(bǔ)丁包并應(yīng)用它”。-oh明確指定Oracle Home路徑防止Opatch誤讀注冊(cè)表取到錯(cuò)誤的ORACLE_HOME。-oh后面這個(gè)路徑就是剛才set的ORACLE_HOME兩條都寫(xiě)雙保險(xiǎn)。執(zhí)行過(guò)程中Opatch會(huì)先做依賴(lài)檢查和沖突檢查屏幕滾動(dòng)輸出Prerequisite check等字樣任何一處失敗都會(huì)中止。遇到Conflict信息時(shí)停止操作查看具體沖突的是哪個(gè)補(bǔ)丁和現(xiàn)有補(bǔ)丁是否產(chǎn)生文件級(jí)別的覆蓋沖突。在12c環(huán)境里如果之前裝了一個(gè)老PSU現(xiàn)在要裝一個(gè)新的OJVM補(bǔ)丁兩者改的文件可能重疊Opatch會(huì)拒絕繼續(xù)這是正常保護(hù)機(jī)制不能加別的參數(shù)繞過(guò)。apply過(guò)程中還有一個(gè)常見(jiàn)的交互提示Please enter the home name或類(lèi)似詢(xún)問(wèn)home名稱(chēng)。Windows下opatch傾向于從注冊(cè)表自動(dòng)獲取但遇到多個(gè)Oracle HOME時(shí)它會(huì)分不清讓你手動(dòng)輸入home名。此時(shí)不要盲打用注冊(cè)表編輯器看一下KEY_OraDB12Home1鍵名去掉KEY_前綴的那個(gè)字符串比如OraDB12Home1輸入它再回車(chē)。補(bǔ)丁日志是排查問(wèn)題的第一手信息apply失敗時(shí)日志位置在%ORACLE_HOME%\cfgtoollogs\opatch\opatch2024-01-01_10-30-00.log日志文件名帶時(shí)間戳定位到最新一個(gè)。Windows下opatch日志寫(xiě)得比Linux詳細(xì)因?yàn)樗鼤?huì)把Java的堆棧信息也打進(jìn)去搜ERROR、WARNING、FAILED三個(gè)關(guān)鍵字往往能直接定位到問(wèn)題行。apply成功后屏幕提示OPatch succeeded此時(shí)數(shù)據(jù)庫(kù)服務(wù)還沒(méi)重啟內(nèi)存里跑的仍然是舊代碼——補(bǔ)丁只是把磁盤(pán)文件更新了要讓Oracle實(shí)例加載新文件必須重啟數(shù)據(jù)庫(kù)服務(wù)。在Windows服務(wù)管理器里找到OracleServiceORCL右鍵重啟再用sqlplus驗(yàn)證補(bǔ)丁是否真正生效。驗(yàn)證方法在最后一章單獨(dú)說(shuō)。4. 在12c上打補(bǔ)丁常見(jiàn)問(wèn)題避坑現(xiàn)象、原因、解決4.1 現(xiàn)象一opatch不是內(nèi)部或外部命令輸入opatch version報(bào)錯(cuò)opatch 不是內(nèi)部或外部命令也不是可運(yùn)行的程序或批處理文件。原因有兩個(gè)一是當(dāng)前cmd窗口的PATH環(huán)境變量里沒(méi)有包含%ORACLE_HOME%\OPatch目錄Windows不會(huì)像Linux那樣自動(dòng)把ORACLE_HOME加進(jìn)PATH二是命令拼寫(xiě)少寫(xiě)了.bat擴(kuò)展名。有少數(shù)人把opatch當(dāng)成一個(gè)exe直接運(yùn)行Windows下可執(zhí)行文件是opatch.bat。解決很簡(jiǎn)單兩種做法任選。第一種是臨時(shí)進(jìn)入目錄執(zhí)行cd /d %ORACLE_HOME%\OPatch opatch.bat version第二種是一勞永逸把OPatch目錄加進(jìn)當(dāng)前會(huì)話(huà)的PATHset PATH%ORACLE_HOME%\OPatch;%PATH% opatch.bat version我習(xí)慣用第二種整個(gè)打補(bǔ)丁過(guò)程中多次使用opatch每次都切目錄容易搞錯(cuò)路徑。注意set PATH只對(duì)當(dāng)前cmd窗口有效重開(kāi)窗口需重新執(zhí)行。4.2 現(xiàn)象二apply時(shí)報(bào)錯(cuò)“Insufficient permission”或“Access is denied”現(xiàn)象是opatch apply跑起來(lái)后在復(fù)制文件階段報(bào)java.io.IOException: Access is denied或者Insufficient permission to write to ...補(bǔ)丁中止。原因基本是cmd窗口沒(méi)有管理員權(quán)限。Windows的用戶(hù)賬戶(hù)控制UAC默認(rèn)會(huì)限制標(biāo)準(zhǔn)用戶(hù)對(duì)C:\Program Files、C:\app等目錄的寫(xiě)權(quán)限而ORACLE_HOME恰恰裝在這樣的路徑下。另外還有一種隱蔽情況如果ORACLE_HOME是裝好后又從別的機(jī)器拷貝過(guò)來(lái)的NTFS文件權(quán)限里沒(méi)有給當(dāng)前登錄用戶(hù)任何寫(xiě)權(quán)限。解決方法是右鍵“命令提示符”圖標(biāo)選擇“以管理員身份運(yùn)行”然后再執(zhí)行apply。如果是拷貝過(guò)來(lái)的ORACLE_HOME還需要主動(dòng)給目錄授權(quán)cmd下執(zhí)行icacls C:\app\oracle /grant %USERNAME%:(OI)(CI)F /T /Cicacls的參數(shù)含義/grant授予指定用戶(hù)權(quán)限%USERNAME%是當(dāng)前用戶(hù)名(OI)(CI)表示容器繼承和對(duì)象繼承F是完全控制/T遞歸所有子目錄/C遇到錯(cuò)誤繼續(xù)執(zhí)行。執(zhí)行完重新打開(kāi)一個(gè)管理員cmd再做apply。這里建議不要跳過(guò)授權(quán)直接關(guān)UAC關(guān)UAC會(huì)讓服務(wù)器整體暴露在風(fēng)險(xiǎn)里不值得。4.3 現(xiàn)象三打補(bǔ)丁提示“OPatch detected that the current ORACLE_HOME is not registered”現(xiàn)象是執(zhí)行apply時(shí)Opatch直接退出提示OPatch detected that the current ORACLE_HOME is not registered in the Central Inventory。原因有兩個(gè)方向。一是注冊(cè)表里Oracle inventory確實(shí)沒(méi)有這個(gè)HOME記錄常見(jiàn)于從別的機(jī)器克隆過(guò)來(lái)的環(huán)境中央inventory目錄C:\Program Files\Oracle\Inventory沒(méi)有被一起遷移。二是當(dāng)前cmd里set的ORACLE_HOME和注冊(cè)表里登記的路徑不一致Opatch對(duì)比后發(fā)現(xiàn)兩邊對(duì)不上。解決的思路是讓inventory重新認(rèn)識(shí)這個(gè)HOME常見(jiàn)做法是手動(dòng)修改C:\Program Files\Oracle\Inventory\ContentsXML\oui-oraclehome.xml。用記事本打開(kāi)看里面有沒(méi)有一行Home NAMEOraDb12Home1 LOCC:\app\oracle\product\12.2.0\dbhome_1 TYPEO IDX1/如果沒(méi)有或路徑不對(duì)加上或改成實(shí)際路徑。改之前先備份這個(gè)文件。改完再跑opatch.bat lsinventory驗(yàn)證。要留意編輯器不要選擇帶UTF-8 BOM的XML文件里多一個(gè)BOM頭會(huì)讓Java解析失敗。提示不要直接刪除oui-oraclehome.xml指望Opatch自動(dòng)重建那會(huì)讓inventory丟失所有歷史補(bǔ)丁記錄連回滾的資格都沒(méi)了。4.4 現(xiàn)象四補(bǔ)丁apply成功但SQL語(yǔ)句執(zhí)行計(jì)劃沒(méi)變化或alert日志里有ORA-錯(cuò)誤apply顯示OPatch succeeded但重啟數(shù)據(jù)庫(kù)后查相關(guān)Bug修復(fù)的效果沒(méi)有體現(xiàn)。這里要區(qū)分“文件補(bǔ)丁”和“數(shù)據(jù)庫(kù)字典補(bǔ)丁”兩個(gè)層級(jí)。原因在于12c的很多補(bǔ)丁分成兩部分文件替換opatch apply完成和SQL字典更新需要datapatch工具完成。Windows上主要負(fù)責(zé)sql字典變更的工具叫datapatch它位于%ORACLE_HOME%\OPath\datapatch——注意拼寫(xiě)是datapatch不是datapatch.bat。這個(gè)細(xì)節(jié)經(jīng)常被Windows用戶(hù)忽略apply成功只是文件級(jí)完成如果README說(shuō)明需要datapatch那必須額外執(zhí)行。解決方法是管理員cmd下執(zhí)行cd /d %ORACLE_HOME%\OPatch datapatch.bat -verbose-verbose參數(shù)打印每個(gè)SQL腳本的執(zhí)行日志。執(zhí)行前數(shù)據(jù)庫(kù)實(shí)例必須是啟動(dòng)狀態(tài)否則datapatch連不上實(shí)例會(huì)直接失敗。執(zhí)行成功后再查opatch lsinventory -detail里補(bǔ)丁對(duì)應(yīng)的SQL狀態(tài)不再是Not Applied或Pending。4.5 現(xiàn)象五回滾時(shí)報(bào)“Patch is not installed”或“Rollback was not successful”補(bǔ)丁打錯(cuò)了或者行為異常決定執(zhí)行opatch rollback -id 補(bǔ)丁號(hào)結(jié)果Opatch說(shuō)這個(gè)補(bǔ)丁沒(méi)裝過(guò)回滾拒絕執(zhí)行。原因大概率是執(zhí)行回滾的ORACLE_HOME和當(dāng)初打補(bǔ)丁時(shí)用的ORACLE_HOME不一致——可能是環(huán)境變量設(shè)置錯(cuò)了也可能有兩個(gè)Oracle HOME都用同一個(gè)inventoryOpatch檢索到了錯(cuò)誤的目標(biāo)。還有個(gè)原因是回滾命令寫(xiě)成了opatch rollback -id 29342341但補(bǔ)丁號(hào)前需要加p字母或完整的補(bǔ)丁版本號(hào)。Opatch在這個(gè)命令上對(duì)參數(shù)的匹配要求比較嚴(yán)格。解決的排查步驟是先確認(rèn)環(huán)境再執(zhí)行回滾set ORACLE_HOMEC:\app\oracle\product\12.2.0\dbhome_1 %ORACLE_HOME%\OPatch\opatch.bat lsinventory -oh %ORACLE_HOME% | more在輸出里找到補(bǔ)丁號(hào)那一行看完整寫(xiě)法?;貪L命令和這個(gè)寫(xiě)法保持一致比如%ORACLE_HOME%\OPatch\opatch.bat rollback -id 29342341 -oh %ORACLE_HOME%如果lsinventory -details輸出里確實(shí)有這條補(bǔ)丁記錄但回滾還是報(bào)錯(cuò)最后一個(gè)辦法是去中央inventory里查記錄文件是否和ORACLE_HOME不一致。Windows下這個(gè)目錄在C:\Program Files\Oracle\Inventory\ContentsXML里面有components.xml之類(lèi)的文件按照補(bǔ)丁號(hào)搜索確認(rèn)是否記錄在案。如果記錄文件損壞那不是回滾能解決的得做inventory恢復(fù)這個(gè)操作風(fēng)險(xiǎn)高建議先聯(lián)系Oracle支持。5. 打補(bǔ)丁后怎么驗(yàn)證和后悔檢查命令與回滾路徑5.1 三步驗(yàn)證補(bǔ)丁真實(shí)生效很多人apply成功就覺(jué)得完事了其實(shí)那只是第一步。完整的驗(yàn)證分三步。第一步是文件級(jí)驗(yàn)證用opatch lsinventory確認(rèn)補(bǔ)丁已進(jìn)入清單%ORACLE_HOME%\OPatch\opatch.bat lsinventory -details -oh %ORACLE_HOME% | findstr /i 29342341findstr /i忽略大小寫(xiě)查找補(bǔ)丁號(hào)輸出里能看到補(bǔ)丁描述和狀態(tài)。第二步是驗(yàn)證數(shù)據(jù)庫(kù)里補(bǔ)丁對(duì)應(yīng)的SQL變更是否進(jìn)庫(kù)12c的字典補(bǔ)丁狀態(tài)記錄在數(shù)據(jù)庫(kù)里select patch_id, patch_uid, description, status, action_time from dba_registry_sqlpatch order by action_time;正常狀態(tài)是SUCCESS如果看到FAILED或WITH ERRORS需要用datapatch重新執(zhí)行失敗的部分。第三步是功能抽查找到這個(gè)補(bǔ)丁修復(fù)的Bug號(hào)在Bug描述里對(duì)應(yīng)到一個(gè)可操作的SQL行為實(shí)際執(zhí)行一遍確認(rèn)行為符合修復(fù)預(yù)期。我打過(guò)幾次補(bǔ)丁后發(fā)現(xiàn)第二步和第三步偶爾會(huì)不一致比如字典更新顯示SUCCESS但實(shí)際行為沒(méi)變這時(shí)候多半是實(shí)例服務(wù)沒(méi)真正重啟舊代碼還在內(nèi)存里完全停掉服務(wù)再起來(lái)一次基本能解決。5.2 Windows下回滾要注意的細(xì)節(jié)回滾是最后的后悔藥但Windows上回滾比Linux多兩個(gè)陷阱。一是回滾前必須停止Oracle數(shù)據(jù)庫(kù)服務(wù)否則文件被進(jìn)程占用回滾時(shí)報(bào)無(wú)法刪除文件。二是回滾后同樣需要重新執(zhí)行datapatch把字典變更撤回。完整命令序列是net stop OracleServiceORCL %ORACLE_HOME%\OPatch\opatch.bat rollback -id 29342341 -oh %ORACLE_HOME% net start OracleServiceORCL cd /d %ORACLE_HOME%\OPatch datapatch.bat -verbose回滾執(zhí)行完成后務(wù)必再跑一次opatch.bat lsinventory確認(rèn)清單里已經(jīng)看不到這個(gè)補(bǔ)丁。我的個(gè)人習(xí)慣是打補(bǔ)丁前先在測(cè)試庫(kù)上完整走一遍apply和rollback用筆記記下每條命令的實(shí)際輸出然后到生產(chǎn)環(huán)境時(shí)照著筆記執(zhí)行。這樣做的好處是能分辨哪些報(bào)錯(cuò)是環(huán)境差異、哪些是操作失誤真到了凌晨?jī)牲c(diǎn)在生產(chǎn)庫(kù)上出問(wèn)題時(shí)這份筆記比臨場(chǎng)翻文檔救命得多。希望這些Windows上的Oracle 12c補(bǔ)丁操作細(xì)節(jié)能幫到你至少讓下次打補(bǔ)丁別在第一步就卡住。本文還有配套的精品資源點(diǎn)擊獲取