這個問題的根本原因是Windows Oracle數據庫的BT設計(unix/Linux無此問題)。
一、Oracle的網絡通信端口原理
Oracle數據庫的網絡訪問采用了一個很BT的工作模式,其大概流程如下:
1)oracle server上的Oracle net listener進程持續監聽一個固定的TCP端口(缺省是1521);
2)clIEnt向server上的net listener端口發起連接請求;
3)listenr收到client的請求之後,建立與clIEnt的連接,並通知server新建一個數據庫連接的服務進程(以下簡稱P),該進程會隨機選擇一個沒有被使用的TCP端口並綁定,然後將端口號通知listener;
4)listenr將P綁定的端口號轉發給clIEnt;
5)clIEnt收到P的端口號後,終止與listener的連接,然後通過P的綁定端口直接連接P;
到第5步,連接才最終完成,之後clIEnt就可以訪問數據庫了。
從上面的工作流程可以知道,在這種工作模式下,clIEnt實際最終連接的Oracle server端口是隨機的。
所以根本無法在防火牆上預先設定固定的TCP端口來使Oracle server可以被訪問。
據說oracle這麼做也是不得已的,因為早期Windows nt的TCP/IP部分有bug,直接使用公用端口連接會有問題,所以Oracle才搞出這麼個天才的設計。
不過,NT4SP3之後不就沒這個bug了嗎,為啥到oracle 11g了還在用這個BT模式呢? 當然啦,現在網絡安全性問題這麼嚴重,如果真的無法使用防火牆,Windows版的Oracle數據庫豈不是要賣不出去了嗎?
oracle公司當然不會那麼白癡,從oracle 8i開始,Windows版的Oracle也可以使用正常的工作模式了,只不過默認仍是使用BT工作模式罷了。
只有Windows平台上的9i及以下版本的Oracle才會有這個問題。Oracle在Linux以及Unix平台下,多個進程間可以對端口進行復用,Oracle Server Process仍然使用的是跟監聽進程一個端口(1521),客戶端只連接了一次,並沒有進行第二次連接,與上面描述的流程相比已經發生了變化。
在Windows平台上,10g及以上版本的數據庫,也同樣利用端口復用,避免了這樣的問題。實際上10g就是默認USE_SHARED_SOCKET為TRUE。
二、在防火牆中設置程序例外
在Oracle的BT模式下,其實可通過在防火牆中設置Oracle程序例外來穿越防火牆。
三、在防火牆中設置端口例外
在Windows注冊表的 (HOMEDIR是你機器上安裝的Oracle數據庫的instance名稱)中添加一個字符串鍵值,名稱為USE_SHARED_SOCKET,值為TRUE(注意大小寫),然後重啟Oracle instance或直接重啟Windows就OK了。
這樣,你只要再在防火牆上打開oracle的監聽端口(缺省為1521),就可以在防火牆外訪問Oracle了!
需要在MTS模式下(共享模式) Oracle默認是專用模式。 經試驗發現,如果不在init文件中設參數的話,Oracle仍然會要求一個隨機端口和1521端口來共同通訊,只是這個隨機端口,並不隨客戶端會話和登 錄的變化而變化,在沒有重啟服務器時,是固定的。 (試驗發現,在專用模式下,每次連接,Oracle服務器會按+1方式,提供一個非1521的端口。) 所以,還需要在init.ora文件的最後加上一條參數:
mts_dispatchers="(address=(protocol=tcp)(host=myoradb)(port=1521))(dispatchers=1)" 這樣才真正實現只用一個端口,穿過防火牆。