實(shí)戰(zhàn))
簡(jiǎn)介面向64位Windows平臺(tái)上的.NET開(kāi)發(fā)人員與數(shù)據(jù)庫(kù)管理員Oracle數(shù)據(jù)訪問(wèn)組件ODAC 12.2.0.1.0提供完整的數(shù)據(jù)連接中間件包含面向.NET 4與.NET 2.0的數(shù)據(jù)提供程序、ASP.NET驅(qū)動(dòng)、OLE DB接口以及Oracle事務(wù)服務(wù)能夠滿足不同版本項(xiàng)目的連接需求適用于常規(guī)數(shù)據(jù)訪問(wèn)、Web應(yīng)用及分布式事務(wù)等場(chǎng)景。組件包內(nèi)置即時(shí)客戶(hù)端、依賴(lài)運(yùn)行庫(kù)與自動(dòng)化配置腳本可將原本繁瑣的環(huán)境部署轉(zhuǎn)化為批量命令操作適合在生產(chǎn)環(huán)境快速上線或遷移。整個(gè)資源共179個(gè)文件以DLL核心庫(kù)為主輔以SQL腳本、PLB存儲(chǔ)過(guò)程包、SYM符號(hào)文件、CONFIG配置文件、EXE工具、BAT批處理腳本及HTML說(shuō)明文檔壓縮包大小73.48MB。其中BAT腳本覆蓋安裝、卸載與注冊(cè)表配置SQL和存儲(chǔ)過(guò)程文件用于初始化數(shù)據(jù)庫(kù)對(duì)象、驗(yàn)證環(huán)境連通性目錄結(jié)構(gòu)清晰能夠按需提取對(duì)應(yīng)模塊。目前已有1538人瀏覽學(xué)習(xí)可直接用于搭建64位Oracle連接鏈路也可作為企業(yè)應(yīng)用開(kāi)發(fā)中的集成參考幫助團(tuán)隊(duì)減少兼容性排查時(shí)間。 第一次拿到 ODAC122010Xcopy-x64.zip 這個(gè)壓縮包的時(shí)候我一度懷疑自己是不是下載錯(cuò)了東西。沒(méi)有 setup.exe沒(méi)有友好的安裝向?qū)Ы鈮撼鰜?lái)就是一堆 dll、exe 和一個(gè)看起來(lái)平平無(wú)奇的 install.bat??删褪沁@么其貌不揚(yáng)的一個(gè)包在被困在“服務(wù)器上沒(méi)有管理員權(quán)限但 .NET 服務(wù)必須連 Oracle”的場(chǎng)合里救了我一命。不少人和我當(dāng)時(shí)的處境類(lèi)似電腦沒(méi)裝完整 Oracle 客戶(hù)端、公司在域環(huán)境里不給提權(quán)或者只是想在某臺(tái)測(cè)試機(jī)上臨時(shí)跑幾條 SQL 腳本。ODAC 12.2.0.1.0 的 Xcopy 版本正是為這些“不想走標(biāo)準(zhǔn)安裝流程”的場(chǎng)景準(zhǔn)備的。這篇就按我自己實(shí)際操作的順序講講這個(gè)包到底是什么、怎么部署以及部署后最容易踩的幾個(gè)坑。1. 為什么明明有完整客戶(hù)端我還要抱著這個(gè) zip 不放很多人第一次接觸 ODAC Xcopy都會(huì)冒出同一個(gè)疑問(wèn)Oracle 官方明明有安裝版客戶(hù)端我為什么要用一個(gè)免安裝的 zip真有好事我的答案是在特定場(chǎng)景下它確實(shí)比完整客戶(hù)端合適得多。1.1 ODAC、Instant Client、完整客戶(hù)端三個(gè)概念先別混我見(jiàn)過(guò)太多報(bào)錯(cuò)根源就是把這三個(gè)東西混為一談。完整 Oracle Client 是圖形化安裝向?qū)аb完之后會(huì)出現(xiàn)在“程序和功能”里體積動(dòng)輒幾個(gè) G集成了 OCI、JDBC、ODBC、SQL*Plus、開(kāi)發(fā)工具等一大堆組件適合開(kāi)發(fā)機(jī)和需要完整功能的環(huán)境但放到生產(chǎn)服務(wù)器或者 CI 機(jī)器上就顯得特別笨重。Instant Client 是更精簡(jiǎn)的客戶(hù)端運(yùn)行庫(kù)只有 OCI、SQLPlus 這些基礎(chǔ)內(nèi)容體積幾百 MB也是解壓就能用適合“只需要連庫(kù)跑查詢(xún)”的場(chǎng)景。而 ODAC 全稱(chēng)是 Oracle Data Access Components是面向開(kāi)發(fā)者的數(shù)據(jù)訪問(wèn)組件集里面既有 ODP.NET、Oracle Provider for OLE DB 這類(lèi)驅(qū)動(dòng)也通常連帶打包 Instant Client 和 SQLPlus。所以 ODAC Xcopy 這個(gè)包更像是一個(gè)“開(kāi)發(fā)者工具包加上最小客戶(hù)端”的融合體。x64 就更好理解了里面的 DLL 和工具都是 64 位的。12.2.0.1.0 對(duì)應(yīng) Oracle Database 12c Release 2這個(gè)版本在 ODP.NET 生態(tài)里很有代表性它同時(shí)提供托管驅(qū)動(dòng)和非托管驅(qū)動(dòng)連接方式既支持老的 TNS 別名也支持 host:port/service_name 直連兼容性相當(dāng)好。1.2 Xcopy 模式和常規(guī)安裝的本質(zhì)差異常規(guī)安裝版通過(guò) Oracle Universal Installer 寫(xiě)入系統(tǒng)注冊(cè)表、服務(wù)、PATH 都會(huì)被自動(dòng)打理好但一旦需要重裝或者遷移代價(jià)很大。Xcopy 模式突出一個(gè)“可控”解壓到目標(biāo)目錄要么運(yùn)行 install.bat 做系統(tǒng)級(jí)配置要么手動(dòng)設(shè)置環(huán)境變量讓?xiě)?yīng)用從此目錄加載驅(qū)動(dòng)。對(duì)比項(xiàng)ODAC Xcopy常規(guī)安裝版安裝方式解壓 zip運(yùn)行 install.bat 或手動(dòng)配置OUI 向?qū)Ш笈_(tái)寫(xiě)注冊(cè)表和系統(tǒng)服務(wù)管理員權(quán)限大多數(shù)場(chǎng)景不需要運(yùn)行 install.bat 時(shí)可能需要基本必須目錄獨(dú)立性任意目錄可隨包遷移通常鎖定在 ORACLE_HOME可復(fù)制性復(fù)制到干凈機(jī)器稍配置即可需要重新安裝過(guò)程適用場(chǎng)景CI/CD、無(wú) GUI 的 Windows 服務(wù)器、離線環(huán)境開(kāi)發(fā)機(jī)、需要完整 Oracle 功能的機(jī)器簡(jiǎn)單說(shuō)完整客戶(hù)端適合“我要在電腦上長(zhǎng)期搞 Oracle 開(kāi)發(fā)”Xcopy 適合“我只要讓這個(gè)應(yīng)用能連上 Oracle”。2. 從解壓到跑通 SQL*Plus 的完整部署路徑既然標(biāo)題就是 ODAC 12.2.0.1.0 的 x64 Xcopy 包我就以 Windows 環(huán)境為例走一遍標(biāo)準(zhǔn)流程。2.1 目錄放哪TNS_ADMIN 為什么單獨(dú)拎出來(lái)我習(xí)慣把包解壓到一個(gè)不含中文、不含空格的路徑比如C:\lib\odac122010xcopy。路徑里有空格某些老組件的腳本會(huì)處理得比較痛苦干脆一開(kāi)始就規(guī)避。解壓后通常能看到類(lèi)似odac、instantclient_12_2的子目錄不同版本命名可能有點(diǎn)差異但不影響整體思路。關(guān)鍵的一步是設(shè)置三個(gè)環(huán)境變量set ORACLE_HOMEC:\lib\odac122010xcopy set PATH%ORACLE_HOME%\instantclient_12_2;%PATH% set TNS_ADMINC:\lib\oracle_network\admin這里重點(diǎn)說(shuō)TNS_ADMIN。很多人會(huì)把 tnsnames.ora 直接放在解壓包內(nèi)的 network/admin 目錄里我不推薦這么做。原因特別實(shí)際以后你要是升級(jí) ODAC 或者換個(gè)路徑重新解壓包內(nèi)文件很可能被覆蓋你的連接配置就沒(méi)了。把TNS_ADMIN指向包外的獨(dú)立目錄比如C:\lib\oracle_network\admin升級(jí)包對(duì)配置完全無(wú)感。這個(gè)習(xí)慣幫我省過(guò)不少事。在TNS_ADMIN目錄下創(chuàng)建tnsnames.ora內(nèi)容類(lèi)似ORCL (DESCRIPTION (ADDRESS (PROTOCOL TCP)(HOST 192.168.1.10)(PORT 1521)) (CONNECT_DATA (SERVER DEDICATED) (SERVICE_NAME orcl) ) )如果還需要sqlnet.ora也放在同一個(gè)目錄比如設(shè)置SQLNET.AUTHENTICATION_SERVICES (NONE)或(NTS)按你的認(rèn)證需求來(lái)。2.2 用 EZ Connect 先驗(yàn)證網(wǎng)絡(luò)層別一上來(lái)就測(cè)別名部署完環(huán)境變量第一步我建議先用 EZ Connect 形式直接測(cè) SQL*Plus繞開(kāi) tnsnames.ora 的解析干擾sqlplus scott/tiger192.168.1.10:1521/orcl這一步能通說(shuō)明客戶(hù)端底層網(wǎng)絡(luò)棧沒(méi)問(wèn)題你能連上監(jiān)聽(tīng)和服務(wù)。如果這里就報(bào) ORA-12154 或 ORA-12514那問(wèn)題多半在連接串本身、監(jiān)聽(tīng)狀態(tài)或者服務(wù)名而不是 Xcopy 包的問(wèn)題。EZ Connect 通了之后再測(cè) TNS 別名tnsping ORCL sqlplus scott/tigerORCLtnsping只能測(cè)到監(jiān)聽(tīng)是否響應(yīng)不能驗(yàn)證賬號(hào)密碼和服務(wù)名。它是用來(lái)定位“到底是網(wǎng)絡(luò)層問(wèn)題還是業(yè)務(wù)層問(wèn)題”的工具別指望它能代替完整連接測(cè)試。3. ODP.NET 的注冊(cè)與配置文件最容易翻車(chē)的環(huán)節(jié)命令行通了不代表 .NET 程序就一定能跑。ODP.NET 在 Xcopy 部署下有兩個(gè)完全不同的版本很多人栽在這里。3.1 托管驅(qū)動(dòng)和非托管驅(qū)動(dòng)選擇會(huì)改變一切ODAC 12.2 里常見(jiàn)的兩類(lèi) ODP.NET一類(lèi)是托管驅(qū)動(dòng)Oracle.ManagedDataAccess.dll純 .NET 實(shí)現(xiàn)不依賴(lài)本機(jī)oci.dll也不需要TNS_ADMIN連接串里直接寫(xiě)host:port/service_name就行。另一類(lèi)是非托管驅(qū)動(dòng)Oracle.DataAccess.dll它必須加載 native 層 DLL依賴(lài) PATH 和 TNS_ADMIN位數(shù)也必須和進(jìn)程完全匹配。我的建議很直接新項(xiàng)目能用托管驅(qū)動(dòng)就優(yōu)先用托管驅(qū)動(dòng)它能砍掉一半以上的環(huán)境類(lèi)問(wèn)題。但老代碼如果已經(jīng)引用了Oracle.DataAccess命名空間并且用到了一些特有 API遷移成本可能很高那就老老實(shí)實(shí)保證 PATH、位數(shù)、版本三者一致。3.2 DbProviderFactories 配置少一步就找不著 Provider非托管驅(qū)動(dòng)在 .NET 里通常需要在 config 中注冊(cè) Provider Factory否則程序一運(yùn)行就報(bào)“找不到請(qǐng)求的 .Net Framework Data Provider”。Xcopy 包如果跑了 install.bat可能會(huì)幫你把 machine.config 寫(xiě)進(jìn)去但如果像我一樣手動(dòng)部署就得在應(yīng)用的app.config或web.config里補(bǔ)一段system.data DbProviderFactories add nameOracle Data Provider for .NET invariantOracle.DataAccess.Client descriptionOracle Data Provider for .NET typeOracle.DataAccess.Client.OracleClientFactory, Oracle.DataAccess, Version4.122.1.0, Cultureneutral, PublicKeyToken89b483f429c473a8 / /DbProviderFactories /system.data托管驅(qū)動(dòng)對(duì)應(yīng)的注冊(cè)段類(lèi)似add nameOracle Data Provider for .NET, Managed Driver invariantOracle.ManagedDataAccess.Client descriptionOracle Data Provider for .NET, Managed Driver typeOracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version4.122.1.0, Cultureneutral, PublicKeyToken89b483f429c473a8 /注意一個(gè)細(xì)節(jié)Version和PublicKeyToken要以解壓出來(lái)的 DLL 實(shí)際屬性為準(zhǔn)。我之前就因?yàn)橹苯訌?fù)制網(wǎng)上的配置沒(méi)改版本號(hào)白白排查了半天。3.3 32 位進(jìn)程撞上 64 位驅(qū)動(dòng)錯(cuò)誤長(zhǎng)得像 .NET 的問(wèn)題x64 包里的 native DLL 是 64 位但你的應(yīng)用程序進(jìn)程可能是 32 位。最常見(jiàn)的一種情況是 IIS 應(yīng)用池里開(kāi)啟了“啟用 32 位應(yīng)用程序”或者老系統(tǒng)里某個(gè)服務(wù)被強(qiáng)制編譯成 x86這時(shí)候加載 64 位 DLL 會(huì)報(bào)BadImageFormatException字面上看像是代碼問(wèn)題實(shí)際是位數(shù)不匹配。遇到這種問(wèn)題先去確認(rèn)進(jìn)程位數(shù)再看包是 x64 還是 x86。如果應(yīng)用必須跑 32 位那就得找對(duì)應(yīng)的 x86 版 ODAC而不是在代碼層面折騰。4. 連接失敗排查ORA 錯(cuò)誤碼背后的共同病因Xcopy 部署免安裝但排錯(cuò)的邏輯反而更清晰。我總結(jié)過(guò)一套從客戶(hù)端到數(shù)據(jù)庫(kù)逐層拆的排查鏈路照著走能少繞很多彎。4.1 常見(jiàn)錯(cuò)誤碼速查錯(cuò)誤碼 / 異常含義最常見(jiàn)原因先查什么ORA-12154TNS 無(wú)法解析連接標(biāo)識(shí)符別名不在 tnsnames.ora或 TNS_ADMIN 沒(méi)指向正確目錄tnsping 別名確認(rèn) TNS_ADMIN確認(rèn)文件名是 tnsnames.oraORA-12514監(jiān)聽(tīng)當(dāng)前無(wú)法識(shí)別請(qǐng)求的服務(wù)service_name 寫(xiě)錯(cuò)或監(jiān)聽(tīng)里沒(méi)有動(dòng)態(tài)注冊(cè)該服務(wù)用 LSNRCTL STATUS 看監(jiān)聽(tīng)確認(rèn)服務(wù)名ORA-12560協(xié)議適配器錯(cuò)誤本機(jī)連接時(shí)客戶(hù)端與實(shí)例配對(duì)不上常見(jiàn)是 PATH 混入多個(gè)版本或位數(shù)不符檢查 PATH 順序檢查位數(shù)檢查數(shù)據(jù)庫(kù)服務(wù)是否啟動(dòng)BadImageFormatException非 ORA 錯(cuò)誤進(jìn)程位數(shù)和 Oracle 客戶(hù)端位數(shù)不匹配確認(rèn)應(yīng)用是 x86 還是 x644.2 逐層排除的順序第一步先tnsping別名確認(rèn) tnsnames 解析這條鏈路是通的。第二步用sqlplus user/passhost:port/service這種 EZ Connect 方式繞過(guò) tnsnames如果通了問(wèn)題基本鎖定在 TNS_ADMIN 或 tnsnames.ora 內(nèi)容。第三步檢查 PATH 里是不是有多個(gè) Oracle 目錄。機(jī)器上如果曾經(jīng)裝過(guò)老版本 Instant Client前面那個(gè)目錄會(huì)直接決定使用哪個(gè)庫(kù)順序錯(cuò)了就會(huì)被老版本劫持。第四步確認(rèn)應(yīng)用賬戶(hù)有解壓目錄的讀取權(quán)限。IIS 應(yīng)用池賬戶(hù)尤其容易踩這個(gè)坑目錄沒(méi)權(quán)限啟動(dòng)服務(wù)時(shí)加載 DLL 直接失敗。我遇到過(guò)最隱蔽的一次tnsnames.ora 文件內(nèi)容完全正確但文件被保存成 UTF-8 帶 BOM 格式SQL*Plus 解析時(shí)把 BOM 也讀進(jìn)去導(dǎo)致別名永遠(yuǎn)匹配不上。這類(lèi)問(wèn)題最?lèi)盒囊驗(yàn)閠nsping報(bào)錯(cuò)都很正常但就是連不上。解決方法是把文件另存為系統(tǒng) ANSI 編碼或者無(wú) BOM 的 UTF-8。5. 關(guān)于“免安裝”的真相以及復(fù)制克隆時(shí)的注意點(diǎn)到了這一步你的環(huán)境基本能跑通了。但我還是想潑幾盆冷水講幾個(gè) Xcopy 模式容易產(chǎn)生誤解的地方。5.1 “綠色免安裝”不等于零寫(xiě)入如果你完全手動(dòng)部署不運(yùn)行 install.bat通常系統(tǒng)注冊(cè)表不會(huì)被寫(xiě)入什么關(guān)鍵項(xiàng)。但只要你運(yùn)行 install.bat它就可能往注冊(cè)表和 machine.config 里寫(xiě)配置。還有 Oracle Provider for OLE DB 這類(lèi)組件使用時(shí)會(huì)檢查注冊(cè)表里的 Oracle 節(jié)點(diǎn)。所以我更愿意把 Xcopy 定義為“受控寫(xiě)入”而不是絕對(duì)的綠色。真正的一動(dòng)不動(dòng)只能發(fā)生在你手動(dòng)配置 只用 managed ODP.NET 的場(chǎng)景。5.2 把整個(gè)目錄復(fù)制到另一臺(tái)機(jī)器前先問(wèn)三件事第一件事路徑變沒(méi)變。如果你運(yùn)行過(guò) install.bat系統(tǒng)層面的配置可能寫(xiě)死了絕對(duì)路徑換個(gè)目錄就得重新跑腳本或者改配置。第二件事環(huán)境變量配沒(méi)配。復(fù)制目錄只是第一步新機(jī)器的 PATH 和 TNS_ADMIN 必須重新設(shè)置。第三件事目標(biāo)機(jī)器上有沒(méi)有其他 Oracle 環(huán)境。只要有PATH 順序就要小心不能讓它搶跑。我一般建議sensitive 的內(nèi)部工具機(jī)盡量統(tǒng)一用一套固定目錄比如都叫C:\lib\odac122010xcopy這樣腳本復(fù)制過(guò)去只需設(shè)環(huán)境變量不用改任何配置。5.3 什么時(shí)候該換回完整客戶(hù)端Xcopy 能解決 80% 的“程序連 Oracle”場(chǎng)景但如果你需要圖形化 PL/SQL 調(diào)試、需要 SQL Developer 全家桶或者要處理非常復(fù)雜的 Oracle 開(kāi)發(fā)工作它確實(shí)不如完整客戶(hù)端省心。換回完整客戶(hù)端不是丟人的事選工具的標(biāo)準(zhǔn)一直只有一個(gè)——適不適合當(dāng)前場(chǎng)景。拿這個(gè)包踩過(guò)幾次坑之后我現(xiàn)在的基本操作是能選 managed 驅(qū)動(dòng)絕不碰 unmanaged能用 EZ Connect 驗(yàn)證就絕不先調(diào) tnsnames路徑保持絕對(duì)簡(jiǎn)單。這套組合下來(lái)Xcopy 的穩(wěn)定性比大多數(shù)人想象中要高得多。如果你剛好卡在某個(gè)錯(cuò)誤碼上照著上面的鏈路逐層排多半能找到出處。本文還有配套的精品資源點(diǎn)擊獲取