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