丁:Opatch命令詳解與避坑指南)
簡(jiǎn)介針對(duì)Windows平臺(tái)的Oracle 12c補(bǔ)丁工具OPatch資源包面向數(shù)據(jù)庫(kù)管理員與系統(tǒng)運(yùn)維人員解決Windows環(huán)境下應(yīng)用Oracle補(bǔ)丁時(shí)OPatch工具缺失或版本不匹配的問(wèn)題涵蓋補(bǔ)丁檢測(cè)、安裝、回滾等常見(jiàn)維護(hù)場(chǎng)景。壓縮包共454個(gè)文件整體102.88MB以jar、dll、exe等可執(zhí)行與依賴(lài)組件為主輔以bat批處理腳本、properties配置文件、md說(shuō)明文檔及sh輔助腳本構(gòu)成一套完整可用的OPatch工具鏈便于在無(wú)外網(wǎng)環(huán)境離線部署和補(bǔ)丁應(yīng)用。包內(nèi)包含核心的opatch命令與配套的補(bǔ)丁應(yīng)用、數(shù)據(jù)補(bǔ)丁、自動(dòng)補(bǔ)丁等工具以及JVM發(fā)現(xiàn)、WebLogic補(bǔ)丁等輔助腳本并附有證書(shū)、黑名單、字體等環(huán)境配置文件可幫助讀者快速了解Oracle補(bǔ)丁工具的目錄結(jié)構(gòu)、運(yùn)行機(jī)制和典型用法提升補(bǔ)丁管理與排錯(cuò)效率。已有996人學(xué)習(xí)下載適合需要手工維護(hù)Oracle 12c補(bǔ)丁的中高級(jí)DBA與運(yùn)維人員參考。1. 在 Windows 上給 Oracle 12c 打補(bǔ)丁為什么 Opatch 才是真正的入口Windows 服務(wù)器上的 Oracle 12c 要打補(bǔ)丁很多人第一反應(yīng)是在解壓目錄里找 setup.exe雙擊后卻發(fā)現(xiàn)什么都沒(méi)發(fā)生。真正干活的是一套命令行工具 Opatch它負(fù)責(zé)把補(bǔ)丁內(nèi)容寫(xiě)進(jìn) ORACLE_HOME 的二進(jìn)制文件同時(shí)更新 inventory補(bǔ)丁清單少了它補(bǔ)丁包解壓得再整齊也白搭。這篇筆記寫(xiě)給兩類(lèi)人一類(lèi)是剛接手 12c 的 DBA 和運(yùn)維想知道在 Windows 上打補(bǔ)丁到底有哪些步驟、哪些命令必須先驗(yàn)證另一類(lèi)是已經(jīng)打過(guò)幾次補(bǔ)丁但踩過(guò)坑的人比如補(bǔ)丁裝完版本沒(méi)變、文件被占用、回滾失敗這類(lèi)翻車(chē)現(xiàn)場(chǎng)。我會(huì)按“安裝前清單 → apply 與驗(yàn)證 → rollback → 常見(jiàn)坑 → 一鍵封裝”的順序把它講透。2. 準(zhǔn)備階段Opatch 版本核對(duì)、補(bǔ)丁類(lèi)型與 Windows 專(zhuān)屬環(huán)境要求2.1 先分清 12c 的補(bǔ)丁家族CPU、PSU 和 RU 在 Windows 上的叫法Oracle 12c 的補(bǔ)丁體系對(duì)新手相當(dāng)不友好因?yàn)橥瑯咏小按蜓a(bǔ)丁”三個(gè)月一次的和臨時(shí)補(bǔ)的安裝方式完全不同。常見(jiàn)的有 CPUCritical Patch Update每季度發(fā)布主要修安全漏洞會(huì)被后續(xù)補(bǔ)丁覆蓋PSUPatch Set Update是累積性的通常含上一個(gè)季度的 CPU在 12.1 時(shí)代最常見(jiàn)從 12.2 開(kāi)始季度補(bǔ)丁更多以 RURelease Update和 RURRelease Update Revision命名。有一點(diǎn)要記住這些補(bǔ)丁在 Windows 平臺(tái)上不能跨平臺(tái)混用DB 和 GIGrid Infrastructure要分別有對(duì)應(yīng)的補(bǔ)丁包任意拿 Linux 的文件往 Windows 的 ORACLE_HOME 里覆蓋系統(tǒng)直接起不來(lái)。下載下來(lái)的補(bǔ)丁包文件名一般長(zhǎng)這樣p8位補(bǔ)丁號(hào)_版本_MSW-x86-64.zip。中間的MSW-x86-64就是 Microsoft Windows 平臺(tái)標(biāo)記對(duì)應(yīng) Linux 平臺(tái)的Linux-x86-64下載時(shí)一定要看準(zhǔn)。解壓后會(huì)得到一個(gè)同名目錄里面有 README.html、etc 目錄和一堆文件。README.html 是三個(gè)必讀項(xiàng)最低 Opatch 版本、數(shù)據(jù)庫(kù)版本要求12.1.0.2 還是 12.2.0.1、是否需要額外執(zhí)行 SQL 腳本。網(wǎng)上的很多 oracle12c 安裝教程在打補(bǔ)丁這一步都草草帶過(guò)實(shí)際補(bǔ)丁包的規(guī)范遠(yuǎn)比安裝時(shí)復(fù)雜前置條件漏一條就可能白等一個(gè)維護(hù)窗口。2.2 確認(rèn) Opatch 版本版本不對(duì)補(bǔ)丁裝了等于白裝補(bǔ)丁包的 README 里都會(huì)寫(xiě)“最低 Oracle Opatch 版本 12.2.0.1.x”之類(lèi)的硬性要求。如果本機(jī) Opatch 太老apply 會(huì)在前置檢查階段直接失敗報(bào)類(lèi)似于 OUI 權(quán)限不足或版本太舊的錯(cuò)誤根本走不到文件替換那一步。在 Windows 上確認(rèn)版本的方法很簡(jiǎn)單用管理員身份打開(kāi) cmd然后執(zhí)行set ORACLE_HOMED:\app\oracle\product\12.1.0.2\dbhome_1 cd /d %ORACLE_HOME%\OPatch opatch.bat version opatch.bat lsinventory第一行是手動(dòng)指定 ORACLE_HOME避免登錄用戶的環(huán)境變量指向別的數(shù)據(jù)庫(kù)目錄cd /d跨盤(pán)符進(jìn)入 OPatch 目錄保證調(diào)用的批處理是當(dāng)前目錄里的這一份version會(huì)輸出當(dāng)前 Opatch 的版本號(hào)lsinventory會(huì)列出這個(gè) ORACLE_HOME 下已經(jīng)安裝的全部補(bǔ)丁這一步的輸出在后續(xù) analyze 和 rollback 時(shí)都要用它來(lái)對(duì)照。在 Windows 上執(zhí)行時(shí)確認(rèn) cmd 窗口標(biāo)題帶“管理員”字樣否則后面 apply 會(huì)遇到大量權(quán)限類(lèi)報(bào)錯(cuò)白折騰半小時(shí)。如果服務(wù)器上裝過(guò)多個(gè) Oracle 產(chǎn)品PATH 環(huán)境變量里可能殘留著多個(gè) OPatch 路徑最省心的做法是把完整路徑寫(xiě)進(jìn)命令也就是始終用%ORACLE_HOME%\OPatch\opatch.bat而不是裸敲opatch。另外建議把 ORACLE_HOME 寫(xiě)進(jìn)系統(tǒng)環(huán)境變量不寫(xiě)也行但腳本化時(shí)會(huì)麻煩。這里我一般會(huì)在執(zhí)行前順手敲一句where opatch看看系統(tǒng)到底把命令解析到了哪個(gè)目錄如果指向的不是當(dāng)前 ORACLE_HOME后面一定出幺蛾子。2.3 Windows 與 Linux 打補(bǔ)丁的差異服務(wù)、文件鎖和權(quán)限同樣的補(bǔ)丁包Windows 和 Linux 的安裝邏輯完全不一樣。Linux 上可以拿 oracle 用戶直接跑$ORACLE_HOME/OPatch/opatch apply只要數(shù)據(jù)庫(kù)是干凈的大多數(shù)補(bǔ)丁甚至可以在線完成Windows 上最大的敵人是文件鎖。Oracle 的服務(wù)進(jìn)程會(huì)把 dll 加載進(jìn)內(nèi)存opatch 要覆蓋它時(shí)就會(huì)被系統(tǒng)拒絕報(bào)“文件被另一個(gè)進(jìn)程占用”。所以標(biāo)準(zhǔn)做法是打補(bǔ)丁前先把對(duì)應(yīng)的服務(wù)停掉。對(duì)比點(diǎn)Linux 環(huán)境Windows 環(huán)境執(zhí)行用戶oracle 系統(tǒng)用戶管理員 cmd是否需要停服務(wù)多數(shù)補(bǔ)丁不需要建議停 OracleService 和 Listener常見(jiàn)被占用文件少量 so 文件dll、exe 被服務(wù)加載后拒絕覆蓋Opatch 調(diào)用方式$ORACLE_HOME/OPatch/opatch%ORACLE_HOME%\OPatch\opatch.bat補(bǔ)丁平臺(tái)目錄Linux-x86-64MSW-x86-64在 Windows 上打補(bǔ)丁失敗的高頻原因就是OracleServiceORACLE_SID這個(gè)服務(wù)還在運(yùn)行。opatch 不是簡(jiǎn)單的文件復(fù)制它會(huì)調(diào)系統(tǒng) API 替換 dll一旦服務(wù)占用就會(huì)中斷。所以把數(shù)據(jù)庫(kù)服務(wù)和監(jiān)聽(tīng)服務(wù)停掉再 apply是 Windows 上更省心的姿勢(shì)哪怕補(bǔ)丁說(shuō)明寫(xiě)著支持在線。還有一個(gè)老坑解壓路徑不要放在中文目錄或帶空格的路徑里比如D:\數(shù)據(jù)庫(kù)補(bǔ)丁內(nèi)部腳本對(duì)路徑解析特別脆弱放在D:\patch\這種短路徑最省心。環(huán)境變量和 PATH 配置是 Windows 上最常見(jiàn)的翻車(chē)點(diǎn)之一數(shù)據(jù)庫(kù)、JDK、中間件多產(chǎn)品共存的機(jī)器尤其要小心 PATH 里殘留的舊 Opatch 路徑。3. 在 Windows 上執(zhí)行 Opatch apply從補(bǔ)丁解壓到驗(yàn)證的全流程3.1 下載、解壓與 README.html 的三項(xiàng)必讀信息補(bǔ)丁包從官方支持網(wǎng)站下載后先用解壓工具放到短路徑。Windows 10 和 Windows Server 2019 自帶 tar 命令可以直接解壓 zip老系統(tǒng)用 PowerShell 的 Expand-Archive 或 7-Zip 都行cd /d D:\patch tar -xf p12345678_121020_MSW-x86-64.zip解壓后的目錄名和 zip 一致比如p12345678_121020。進(jìn)入目錄后用瀏覽器打開(kāi) README.html重點(diǎn)找一個(gè)章節(jié)叫 Pre-Installation Instructions里面會(huì)寫(xiě)三類(lèi)信息最低 Opatch 版本、數(shù)據(jù)庫(kù)版本要求比如僅適用于 12.1.0.2.0、是否需要額外執(zhí)行 SQL 腳本。第二類(lèi)信息特別容易漏因?yàn)橛行┭a(bǔ)丁只改二進(jìn)制有些還要在數(shù)據(jù)庫(kù)里跑 catupgrd 之類(lèi)的數(shù)據(jù)字典升級(jí)腳本是否執(zhí)行直接決定數(shù)據(jù)庫(kù)起不起得來(lái)。README.html 里如果寫(xiě)了 “Make sure the Oracle service is stopped”那就老老實(shí)實(shí)停服務(wù)別討價(jià)還價(jià)。3.2 沖突分析opatch apply -analyze必須在正式 apply 前跑直接 apply 報(bào)沖突再回滾會(huì)浪費(fèi)大量時(shí)間更糟糕的是可能把一個(gè)本來(lái)健康的數(shù)據(jù)庫(kù)打成“半補(bǔ)丁”狀態(tài)。Opatch 提供了 analyze 模式只做檢查不寫(xiě)文件相當(dāng)于正式操作前的預(yù)檢。這一步我無(wú)論多急都會(huì)做因?yàn)樗軗踝〗^大多數(shù)依賴(lài)沖突cd /d %ORACLE_HOME%\OPatch opatch.bat apply -analyze -oh %ORACLE_HOME% -ph D:\patch\p12345678_121020 echo %ERRORLEVEL%-oh指定 ORACLE_HOME-ph指定補(bǔ)丁目錄兩者都必須是絕對(duì)路徑。analyze 會(huì)檢查補(bǔ)丁與已應(yīng)用補(bǔ)丁的沖突、補(bǔ)丁與二進(jìn)制版本的兼容性、以及補(bǔ)丁內(nèi)部文件是否完整。返回碼為 0 表示通過(guò)非 0 就停在前面輸出的沖突信息里比如它會(huì)直接告訴你“Patch xxx conflicts with patch yyy”。如果想看更細(xì)的依賴(lài)報(bào)告我一般還會(huì)加一句opatch.bat prereq CheckConflictAgainstOHWithDetail -ph D:\patch\p12345678_121020這條會(huì)把每個(gè)文件層面的依賴(lài)都列出來(lái)。analyze 不是百分百保證 apply 一定成功文件鎖、磁盤(pán)空間這類(lèi)運(yùn)行時(shí)問(wèn)題它管不著但它能篩掉九成以上的“裝完起不來(lái)”。3.3 正式 apply命令與執(zhí)行背后的動(dòng)作analyze 通過(guò)后就可以正式應(yīng)用了。在 Windows 上我習(xí)慣先把服務(wù)和監(jiān)聽(tīng)停掉再進(jìn)入 Opatch 目錄執(zhí)行net stop OracleServiceORCL nul 21 net stop OracleOraDB12Home1TNSListener nul 21 cd /d %ORACLE_HOME%\OPatch opatch.bat apply -oh %ORACLE_HOME% -ph D:\patch\p12345678_121020net stop后面的服務(wù)名不固定可以用sc query | findstr /i oracle查實(shí)際服務(wù)名。apply 命令會(huì)做這么幾件事讀取補(bǔ)丁目錄里的配置文件、備份當(dāng)前二進(jìn)制到 ORACLE_HOME 下的.patch_storage目錄、替換 dll 和 exe 文件、更新 SQL 腳本目錄、最后把補(bǔ)丁信息寫(xiě)進(jìn) inventory。整個(gè)過(guò)程中終端會(huì)打印一行行進(jìn)度最后到 100%。Windows 上有兩個(gè)點(diǎn)需要特別提醒一是不要看它長(zhǎng)時(shí)間沒(méi)輸出就 CtrlC卡住時(shí)先看日志%ORACLE_HOME%\cfgtoollogs\opatch\下最新的 log 文件再?zèng)Q定是否干預(yù)二是 apply 完成后一般不會(huì)自動(dòng)啟動(dòng)數(shù)據(jù)庫(kù)需要手動(dòng)啟動(dòng)并按 README 要求執(zhí)行對(duì)應(yīng)的 SQL 腳本。腳本名因補(bǔ)丁而異必須按 README.html 里的說(shuō)明來(lái)猜一個(gè)名字跑反而會(huì)出問(wèn)題。3.4 驗(yàn)證lsinventory 與日志交叉確認(rèn)apply 輸出 100% 并不代表萬(wàn)事大吉。驗(yàn)證要分兩層第一層是確認(rèn) inventory 里出現(xiàn)了這個(gè)補(bǔ)丁第二層是確認(rèn)數(shù)據(jù)庫(kù)層也生效了。第一層用這條命令cd /d %ORACLE_HOME%\OPatch opatch.bat lsinventory -bugs_fixed | findstr 12345678lsinventory會(huì)列出當(dāng)前 ORACLE_HOME 下所有已應(yīng)用補(bǔ)丁加-bugs_fixed會(huì)在每個(gè)補(bǔ)丁下方顯示它修復(fù)的 bug 列表用findstr過(guò)濾剛才的補(bǔ)丁號(hào)能搜到就說(shuō)明 inventory 記錄已經(jīng)寫(xiě)入。但僅憑這條還不夠因?yàn)?Windows 上有過(guò)“文件復(fù)制成功但數(shù)據(jù)庫(kù)進(jìn)程加載的還是舊版本”的情況所以第二層驗(yàn)證要啟動(dòng)數(shù)據(jù)庫(kù)后執(zhí)行一句 SQLselect * from registry$history;看補(bǔ)丁記錄和安裝時(shí)間是否對(duì)得上。如果這里能看到補(bǔ)丁 ID且數(shù)據(jù)庫(kù)版本視圖v$version與補(bǔ)丁說(shuō)明一致才算真正打上了。日志文件也不要急著刪cfgtoollogs\opatch\里保留了 apply 的完整過(guò)程出問(wèn)題時(shí)要靠它判斷卡在哪一步。4. 回滾與補(bǔ)丁清理Windows 上的后悔藥要按這套流程吃4.1 回滾前必須滿足的三個(gè)條件打補(bǔ)丁沒(méi)有后悔藥Opatch 雖然提供了 rollback 命令但也不是無(wú)條件可用的。回滾前必須確認(rèn)三件事第一能拿到當(dāng)初應(yīng)用補(bǔ)丁時(shí)的 patch id 和確切版本最好的來(lái)源是opatch lsinventory的輸出在打補(bǔ)丁當(dāng)天就應(yīng)該順手存一份文本第二有可靠的備份Windows 上最簡(jiǎn)單的方式是打補(bǔ)丁前對(duì) ORACLE_HOME 做一次文件級(jí)副本或整機(jī)快照不要只依賴(lài) opatch 自己備份到.patch_storage的那份第三數(shù)據(jù)庫(kù)實(shí)例和監(jiān)聽(tīng)服務(wù)必須處于停止?fàn)顟B(tài)否則 rollback 時(shí)同樣會(huì)遇到文件占用。這三條缺一條回滾就可能從“后悔藥”變成“二次事故”?;貪L前再看一遍補(bǔ)丁包 README.html 的 Rollback Instructions有的補(bǔ)丁要求回滾后重新啟動(dòng)實(shí)例執(zhí)行更新腳本有的要求回滾后不執(zhí)行任何 SQL 直接啟動(dòng)差別很大。4.2 rollback 命令按 patch id 精準(zhǔn)撤銷(xiāo)回滾用opatch rollback參數(shù)比 apply 更簡(jiǎn)單因?yàn)樗恍枰a(bǔ)丁 ID不需要補(bǔ)丁目錄。操作前先停服務(wù)net stop OracleServiceORCL nul 21 net stop OracleOraDB12Home1TNSListener nul 21 cd /d %ORACLE_HOME%\OPatch opatch.bat rollback -id 12345678 -oh %ORACLE_HOME%-id后面跟的是當(dāng)初 apply 的補(bǔ)丁號(hào)可以在opatch lsinventory里查到注意不要帶p前綴也不帶路徑。rollback 前同樣可以先加一個(gè)-analyze參數(shù)試跑opatch.bat rollback -analyze -id 12345678 -oh %ORACLE_HOME%它會(huì)先檢查當(dāng)前系統(tǒng)中是否有其他補(bǔ)丁依賴(lài)這個(gè)補(bǔ)丁如果有依賴(lài)會(huì)提示沖突。rollback 的執(zhí)行過(guò)程和 apply 相反它會(huì)從.patch_storage目錄里找舊文件覆蓋回去再更新 inventory。如果 rollback 時(shí)報(bào)“Patch 12345678 is not applied”說(shuō)明當(dāng)初 apply 時(shí) inventory 就沒(méi)寫(xiě)成功先查日志確認(rèn)補(bǔ)丁是否真的在系統(tǒng)里再?zèng)Q定是重新 apply 還是直接恢復(fù)備份。4.3 清理日志與臨時(shí)空間別讓 C 盤(pán)靜悄悄爆掉Oracle 的 Opatch 日志默認(rèn)寫(xiě)在%ORACLE_HOME%\cfgtoollogs\opatch\命名格式是opatch_時(shí)間戳.log每次 apply、rollback、analyze 都會(huì)生成新文件。一兩個(gè)補(bǔ)丁看不出問(wèn)題打上三五年這個(gè)目錄輕輕松松積累幾個(gè) GB。驗(yàn)證無(wú)誤后我一般會(huì)把 30 天前的日志壓縮歸檔到別的盤(pán)再刪掉解壓出來(lái)的補(bǔ)丁目錄forfiles /p %ORACLE_HOME%\cfgtoollogs\opatch /s /m *.log /d -30 /c cmd /c del pathforfiles是 Windows 自帶命令/d -30表示只處理 30 天以前的文件/m *.log匹配日志文件/s處理子目錄。另外還要檢查%TEMP%和用戶AppData\Local\Temp下有沒(méi)有 Opatch 留下的臨時(shí)文件apply 過(guò)程中如果異常中斷這里容易殘留幾百 MB 的數(shù)據(jù)。清理時(shí)不要手動(dòng)去刪 ORACLE_HOME 下的文件尤其是.patch_storage目錄那里面保存著所有歷史補(bǔ)丁的備份手動(dòng)刪掉會(huì)讓以后所有 rollback 都失效。日志可以刪補(bǔ)丁目錄可以刪.patch_storage堅(jiān)決不碰。5. Windows 下 Opatch 的避坑指南5 條血淚記錄5.1 apply 時(shí)報(bào)“文件被占用”或“拒絕訪問(wèn)”現(xiàn)象opatch apply 執(zhí)行到一半終端彈紅字提示某個(gè) dll 無(wú)法訪問(wèn)后面跟著“being used by another process”。原因OracleService 服務(wù)還在運(yùn)行目標(biāo)文件已經(jīng)被加載到服務(wù)進(jìn)程里或者是 cmd 窗口沒(méi)有用管理員身份打開(kāi)。解決先執(zhí)行net stop OracleServiceORCL和net stop OracleOraDB12Home1TNSListener再以管理員身份重新打開(kāi) cmd重跑 analyze 和 apply。如果仍然提示占用打開(kāi)任務(wù)管理器檢查是否有殘留的 oracle 進(jìn)程有就直接結(jié)束再重試。5.2 opatch 命令執(zhí)行后提示找不到補(bǔ)丁目錄或版本不對(duì)現(xiàn)象同一個(gè)命令在 A 機(jī)器上跑得好好的在 B 機(jī)器上報(bào)“cannot find opatch”或識(shí)別到的 ORACLE_HOME 完全不對(duì)。原因PATH 里第一個(gè)命中的 opatch.bat 來(lái)自另一個(gè) Oracle 產(chǎn)品目錄或者-ph傳給了一個(gè)帶中文的路徑。解決不依賴(lài) PATH直接敲%ORACLE_HOME%\OPatch\opatch.bat全路徑先跑where opatch看看當(dāng)前解析到的是哪個(gè)目錄補(bǔ)丁解壓目錄統(tǒng)一挪到D:\patch\這種純英文短路徑下再執(zhí)行。這個(gè)坑在裝有多個(gè)版本數(shù)據(jù)庫(kù)的機(jī)器上特別容易踩。5.3 apply 長(zhǎng)時(shí)間卡在 97% 不動(dòng)日志寫(xiě)著 Updating inventory現(xiàn)象進(jìn)度停在 97%超過(guò)十分鐘沒(méi)有新輸出日志最后一行是 “Updating inventory ...”。原因文件替換已經(jīng)完成但 Windows Defender 或第三方殺毒軟件正在掃描剛替換的 dll導(dǎo)致 inventory 更新被臨時(shí)鎖住。解決先等足 15 到 20 分鐘觀察日志文件大小是否還在增長(zhǎng)如果完全停滯在維護(hù)窗口內(nèi)臨時(shí)關(guān)閉實(shí)時(shí)防護(hù)再重試 apply強(qiáng)行結(jié)束進(jìn)程前一定要先看日志確認(rèn)不是正常慢速執(zhí)行。遇到這類(lèi)問(wèn)題最忌諱手快直接 CtrlC 把 inventory 寫(xiě)到一半補(bǔ)丁狀態(tài)會(huì)變成既不在已應(yīng)用列表、文件已被替換的灰色地帶恢復(fù)起來(lái)非常痛苦。5.4 apply 顯示成功但 lsinventory 里 Opatch 版本還是舊的現(xiàn)象補(bǔ)丁說(shuō)明要求 Opatch 版本不低于 12.2apply 過(guò)程也顯示成功但再次查詢opatch version還是原來(lái)的舊版本。原因你執(zhí)行的 version 命令來(lái)自 PATH 中的另一個(gè) opatch而剛才 apply 用的卻是%ORACLE_HOME%\OPatch\opatch.bat也就是說(shuō)“打補(bǔ)丁和查版本”用的是兩套工具自然對(duì)不上。解決所有 Opatch 操作統(tǒng)一用完整路徑先執(zhí)行reg query HKLM\SOFTWARE\ORACLE確認(rèn)系統(tǒng)注冊(cè)表里的 ORACLE_HOME 指向哪里再把當(dāng)前要操作的 ORACLE_HOME 放到所有命令的最前面。見(jiàn)過(guò)不少運(yùn)維在打補(bǔ)丁前忘了這一步最后白忙一整晚。5.5 補(bǔ)丁打完后數(shù)據(jù)庫(kù)無(wú)法啟動(dòng)報(bào) ORA-00600 或無(wú)法識(shí)別文件現(xiàn)象apply 順利結(jié)束啟動(dòng)數(shù)據(jù)庫(kù)時(shí)報(bào) ORA-00600 內(nèi)部錯(cuò)誤或者提示某個(gè) dll 版本不受支持。原因二進(jìn)制替換了一半、數(shù)據(jù)庫(kù)服務(wù)在 apply 過(guò)程中仍在運(yùn)行導(dǎo)致部分動(dòng)態(tài)庫(kù)被寫(xiě)入不全、Windows 平臺(tái)目錄選錯(cuò)。解決不要嘗試在現(xiàn)有狀態(tài)下修復(fù)直接回滾執(zhí)行opatch.bat rollback -id 補(bǔ)丁號(hào) -oh %ORACLE_HOME%回滾后再啟動(dòng)數(shù)據(jù)庫(kù)如果 rollback 也報(bào)錯(cuò)就恢復(fù)打補(bǔ)丁前做的 ORACLE_HOME 備份。回滾成功后把補(bǔ)丁包文件名里的平臺(tái)標(biāo)記再核對(duì)一遍確認(rèn)不是拿 Linux 版補(bǔ)丁硬打在 Windows 上。6. 進(jìn)階技巧用一條批處理把 Opatch 檢查、apply、驗(yàn)證串起來(lái)手工敲命令雖然穩(wěn)但每周都要給不同環(huán)境打補(bǔ)丁時(shí)就嫌煩了。我習(xí)慣把整個(gè)流程封裝成一個(gè)批處理腳本入?yún)⒅挥醒a(bǔ)丁目錄剩下的檢查、停服務(wù)、apply、驗(yàn)證全部交給腳本echo off setlocal set ORACLE_HOMED:\app\oracle\product\12.1.0.2\dbhome_1 set PATCH_DIRD:\patch\p12345678_121020 set OPATCH%ORACLE_HOME%\OPatch\opatch.bat echo [1/5] stop oracle services... net stop OracleServiceORCL nul 21 net stop OracleOraDB12Home1TNSListener nul 21 echo [2/5] check opatch version... call %OPATCH% version echo [3/5] analyze patch... call %OPATCH% apply -analyze -oh %ORACLE_HOME% -ph %PATCH_DIR% if errorlevel 1 goto :fail echo [4/5] apply... call %OPATCH% apply -oh %ORACLE_HOME% -ph %PATCH_DIR% if errorlevel 1 goto :fail echo [5/5] verify... call %OPATCH% lsinventory -bugs_fixed | findstr 12345678 echo done. goto :end :fail echo Opatch failed. check log in %ORACLE_HOME%\cfgtoollogs\opatch\ :end endlocal腳本里的補(bǔ)丁號(hào) 12345678 是示例占位實(shí)際使用時(shí)要把它替換成你下載的補(bǔ)丁 ID同時(shí)把PATCH_DIR改成解壓后的完整目錄。call關(guān)鍵字不能省批處理調(diào)用另一個(gè) bat 文件后如果不加 call當(dāng)前腳本會(huì)直接結(jié)束不再返回errorlevel是 opatch 自己的返回碼analyze 失敗會(huì)停在 fail 分支。腳本最后一步的 findstr 只是簡(jiǎn)單的文本匹配真正上線前我還會(huì)給腳本加一段“啟動(dòng)數(shù)據(jù)庫(kù)后查詢 registry$history”的驗(yàn)證邏輯畢竟 inventory 有記錄不等于數(shù)據(jù)庫(kù)層已經(jīng)生效。腳本本身沒(méi)有對(duì)中文路徑做特殊處理如果服務(wù)端 cmd 默認(rèn)編碼是 GBK建議把腳本另存為 ANSI 編碼防止注釋亂碼導(dǎo)致if errorlevel判斷失效。我當(dāng)初在 Windows 上第一次打 12c 補(bǔ)丁時(shí)就是跳過(guò)了 analyze 直接 apply結(jié)果打出一個(gè)“文件覆蓋失敗但 inventory 已記錄”的怪狀態(tài)回滾又花了兩小時(shí)。從那以后養(yǎng)成的習(xí)慣是analyze 必跑、服務(wù)必停、驗(yàn)證必須查數(shù)據(jù)庫(kù)而不是只看終端輸出。這套腳本是我自己壓箱底的東西希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取