數(shù)據(jù)庫(kù)故障oracle與防火墻
最近有兩次Oracle數(shù)據(jù)庫(kù)故障與防火墻有關(guān)。
最近有兩次Oracle數(shù)據(jù)庫(kù)故障與防火墻有關(guān)。這里的防火墻是硬件網(wǎng)絡(luò)防火墻,而不是軟件防火墻。
先說(shuō)說(shuō)簡(jiǎn)單的。一個(gè)運(yùn)行在Windows系統(tǒng)上的Oracle 9i,客戶端不能連接數(shù)據(jù)庫(kù),但是用tnsping測(cè)試沒(méi)有問(wèn)題。解決問(wèn)題的辦法很簡(jiǎn)單,但是我們?nèi)匀恍枰私庖幌乱疬@個(gè)問(wèn)題的原因。
這個(gè)問(wèn)題首先得從客戶通通過(guò)監(jiān)聽(tīng)連接數(shù)據(jù)庫(kù)的整個(gè)過(guò)程說(shuō)起,此處指專用服務(wù)器連接模式:
服務(wù)器上的監(jiān)聽(tīng)進(jìn)程在1521端口上進(jìn)行偵聽(tīng)
客戶端發(fā)起一個(gè)數(shù)據(jù)庫(kù)連接請(qǐng)求
監(jiān)聽(tīng)進(jìn)程fork一個(gè)Oracle服務(wù)器進(jìn)程(Server Process),也可稱之為影子進(jìn)程 (Shadow Process)。服務(wù)器進(jìn)程選擇一個(gè)大于1024的端口號(hào)進(jìn)行偵聽(tīng),監(jiān)聽(tīng)進(jìn)程把這個(gè)端口號(hào)發(fā)回到客戶端,要求客戶端重新連接這個(gè)指定的端口。
客戶端重新連接監(jiān)聽(tīng)指定的新端口,也就是重新進(jìn)行連接。
客戶端與Server Process直接對(duì)話,不再通過(guò)監(jiān)聽(tīng),進(jìn)行會(huì)話認(rèn)證(登錄),執(zhí)行SQL等等。
從上述過(guò)程可以看到,客戶端最終連接的端口實(shí)際上并不是1521。由于防火墻一般只開(kāi)放了幾個(gè)端口,對(duì)Oracle數(shù)據(jù)庫(kù)只開(kāi)放了1521端口,這樣在客戶端進(jìn)行第二次連接時(shí),不能通過(guò)防火墻,導(dǎo)致連接數(shù)據(jù)庫(kù)失敗。
值得慶幸的是,只有Windows平臺(tái)上的9i及以下版本的Oracle才會(huì)有這個(gè)問(wèn)題。Oracle在Linux以及Unix平臺(tái)下,多個(gè)進(jìn)程間可以對(duì)端口進(jìn)行復(fù)用,Oracle Server Process仍然使用的是跟監(jiān)聽(tīng)進(jìn)程一個(gè)端口(1521)。通過(guò)在linux使用strace跟蹤客戶端連接數(shù)據(jù)庫(kù)的過(guò)程可以發(fā)現(xiàn),客戶端只連接了一次,并沒(méi)有進(jìn)行第二次連接,與上面描述的流程相比已經(jīng)發(fā)生了變化。在Windows平臺(tái)上,10g及以上版本的庫(kù),也同樣利用端口復(fù)用,避免了這樣的問(wèn)題。
那么Windows上運(yùn)行的Oracle 9i怎么解決這個(gè)問(wèn)題呢?答案很簡(jiǎn)單,在Windows注冊(cè)表的\HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOMEn(這里n指Oracle Home的序號(hào),只有一個(gè)Oracle Home時(shí)是0)鍵下面增加一項(xiàng)USE_SHARED_SOCKET,其值為TRUE。然后重啟監(jiān)聽(tīng)及Oracle服務(wù)(注意要重啟Oracle的服務(wù),而不僅僅是重啟數(shù)據(jù)庫(kù)),就可以解決此問(wèn)題。實(shí)際上10g就是默認(rèn)USE_SHARED_SOCKET為TRUE。
對(duì)于這種問(wèn)題,或者是讓防火墻打開(kāi)針對(duì)數(shù)據(jù)庫(kù)主機(jī)的所有端口訪問(wèn),也能解決。但是這種方案往往會(huì)被負(fù)責(zé)安全的人否決。
下面這個(gè)由防火墻導(dǎo)致的問(wèn)題,就相對(duì)復(fù)雜一點(diǎn)了。
某個(gè)應(yīng)用經(jīng)常報(bào)ORA-3113錯(cuò)誤,檢查發(fā)現(xiàn)ORA-3113來(lái)源于數(shù)據(jù)庫(kù)的一個(gè)db link。為了方便下面的描述,將應(yīng)用直接連接的數(shù)據(jù)庫(kù)稱為DB_A,DB_A通過(guò)db link連接的對(duì)端的數(shù)據(jù)庫(kù)稱為DB_B。在DB_B主機(jī)上沒(méi)有發(fā)現(xiàn)任何有關(guān)的trace和日志,應(yīng)用執(zhí)行的SQL也是非常簡(jiǎn)單的SELECT語(yǔ)句,返回的數(shù)據(jù)量也不大。但出錯(cuò)的語(yǔ)句并不是固定的某一個(gè)SQL。在應(yīng)用連接的數(shù)據(jù)庫(kù)DB_A上做ORA-3113 error stack的trace,也沒(méi)有發(fā)現(xiàn)有價(jià)值的東西。
導(dǎo)致ORA-3113錯(cuò)誤的原因很多。大家可以參考ITPUB上的一篇貼子《ORA-03113錯(cuò)誤分析》。
在這個(gè)ORA-3113錯(cuò)誤的問(wèn)題中,數(shù)據(jù)庫(kù)DB_B沒(méi)有任何日志,出現(xiàn)這種情況的一個(gè)很可能的原因是,DB_B上的Server Process已經(jīng)中止,但又不是在執(zhí)行SQL過(guò)程中出錯(cuò)異常中止了,比如被KILL掉,網(wǎng)絡(luò)連接中斷等。被KILL掉這個(gè)原因,首先被排除,因?yàn)檫@個(gè)錯(cuò)誤出現(xiàn)得很多,每天都有。詢問(wèn)維護(hù)人員,稱也沒(méi)有進(jìn)行過(guò)KILL操作。那么最大的可能性應(yīng)該是網(wǎng)絡(luò)了。順著這條線索,我們?cè)?/span>DB_A上用netstat -na命令檢查到DB_B的網(wǎng)絡(luò)連接,與DB_B中v$session中的會(huì)話進(jìn)行比較,發(fā)現(xiàn)DB_A連接到DB_B的數(shù)據(jù)庫(kù)會(huì)話,比netstat 命令看到的網(wǎng)絡(luò)連接數(shù)少得多。
這是一個(gè)重大的突破。首先要懷疑的是防火墻。因?yàn)榉阑饓?dǎo)致Oracle連接異常的情況非常多。訪問(wèn)數(shù)據(jù)庫(kù)的DBA,這兩個(gè)數(shù)據(jù)庫(kù)分別在不同的業(yè)務(wù)網(wǎng)絡(luò)中,中間使用了Cisco的防火墻。請(qǐng)防火墻維護(hù)工程師檢查防火墻的設(shè)置,發(fā)現(xiàn)防火墻設(shè)置了TCP連接超時(shí)(這個(gè)術(shù)語(yǔ)是防火墻工程師告訴給我的,實(shí)際上我個(gè)人認(rèn)為這個(gè)術(shù)語(yǔ)字面含義跟其實(shí)際的作用相差較大)設(shè)置為1小時(shí)。也就是,對(duì)于通過(guò)防火墻的所有TCP連接,如果在1小時(shí)內(nèi)沒(méi)有任何活動(dòng),就會(huì)被防火墻拆除,這樣就會(huì)導(dǎo)致連接中斷。在拆除連接時(shí),也不會(huì)向連接的兩端發(fā)送任何數(shù)據(jù)來(lái)通知連接已經(jīng)拆除。
而出問(wèn)題的業(yè)務(wù)系統(tǒng),使用的高峰期是在正常的工作時(shí)間內(nèi),最高時(shí)會(huì)導(dǎo)致DB_A會(huì)產(chǎn)生數(shù)十個(gè)連接到DB_B。但是在業(yè)務(wù)低谷期或經(jīng)過(guò)一個(gè)晚上,防火墻將拆除大部分甚至是所有的連接。而下一次使用時(shí),應(yīng)用通過(guò)連接池選擇DB_A中的一個(gè)會(huì)話,這個(gè)會(huì)話的db link之前已經(jīng)連接到DB_B,但是網(wǎng)絡(luò)連接已經(jīng)被防火墻拆除,但是這個(gè)會(huì)話并不知道,仍然會(huì)認(rèn)為這個(gè)連接有效,結(jié)果試圖向DB_B提交SQL時(shí),就出現(xiàn)了ORA-3113錯(cuò)誤。
實(shí)際上,很多使用網(wǎng)絡(luò)連接的應(yīng)用,可以使用稱之為KeepAlive的特性,來(lái)保持TCP連接的活動(dòng)性。在打開(kāi)一個(gè)連接時(shí),通過(guò)setsockopt函數(shù),設(shè)置socket為SO_KEEPALIVE,這樣,在OS層,如果一個(gè)TCP連接在指定的時(shí)間內(nèi)沒(méi)有活動(dòng),會(huì)發(fā)送一個(gè)探測(cè)包到連接的對(duì)端,檢測(cè)連接的對(duì)端是否仍然存在。如果這個(gè)時(shí)間小于防火墻中設(shè)置的“超時(shí)”時(shí)間,防火墻就會(huì)檢查到連接中仍然有數(shù)據(jù),就不會(huì)斷開(kāi)這個(gè)連接。
操作系統(tǒng)中keep alive的相關(guān)設(shè)置,不同的系統(tǒng)有不同的設(shè)置方法。比如在Linux中,在sysctl中設(shè)置net.ipv4.tcp_keepalive_time = 120,表示探測(cè)時(shí)間為120秒,即2分鐘。在AIX中,通過(guò)no命令將tcp_keepidle參數(shù)設(shè)置為240,表示探測(cè)時(shí)間為120秒。注意AIX中這個(gè)參數(shù)的單位是1/2秒,而在Linux中是1秒。
還好Oracle提供了類似的機(jī)制。也就是DCD(Dead Conneciton Detection)。在$ORACLE_HOME/network/admin/sqlnet.ora文件中增加如下一行:
expire_time=NNN
這里NNN為分鐘數(shù),Oracle數(shù)據(jù)庫(kù)會(huì)在會(huì)話IDLE時(shí)間超過(guò)這個(gè)指定的時(shí)間時(shí),檢測(cè)這個(gè)會(huì)話的對(duì)端(即客戶端)是否還有效。避免客戶端由于異常退出,導(dǎo)致會(huì)話一直存在。
因此,我們可以通過(guò)在DB_B數(shù)據(jù)庫(kù)中的sqlnet.ora文件中設(shè)置expire_time來(lái)解決上面提到的ORA-3113問(wèn)題。
先說(shuō)說(shuō)簡(jiǎn)單的。一個(gè)運(yùn)行在Windows系統(tǒng)上的Oracle 9i,客戶端不能連接數(shù)據(jù)庫(kù),但是用tnsping測(cè)試沒(méi)有問(wèn)題。解決問(wèn)題的辦法很簡(jiǎn)單,但是我們?nèi)匀恍枰私庖幌乱疬@個(gè)問(wèn)題的原因。
這個(gè)問(wèn)題首先得從客戶通通過(guò)監(jiān)聽(tīng)連接數(shù)據(jù)庫(kù)的整個(gè)過(guò)程說(shuō)起,此處指專用服務(wù)器連接模式:
服務(wù)器上的監(jiān)聽(tīng)進(jìn)程在1521端口上進(jìn)行偵聽(tīng)
客戶端發(fā)起一個(gè)數(shù)據(jù)庫(kù)連接請(qǐng)求
監(jiān)聽(tīng)進(jìn)程fork一個(gè)Oracle服務(wù)器進(jìn)程(Server Process),也可稱之為影子進(jìn)程 (Shadow Process)。服務(wù)器進(jìn)程選擇一個(gè)大于1024的端口號(hào)進(jìn)行偵聽(tīng),監(jiān)聽(tīng)進(jìn)程把這個(gè)端口號(hào)發(fā)回到客戶端,要求客戶端重新連接這個(gè)指定的端口。
客戶端重新連接監(jiān)聽(tīng)指定的新端口,也就是重新進(jìn)行連接。
客戶端與Server Process直接對(duì)話,不再通過(guò)監(jiān)聽(tīng),進(jìn)行會(huì)話認(rèn)證(登錄),執(zhí)行SQL等等。
從上述過(guò)程可以看到,客戶端最終連接的端口實(shí)際上并不是1521。由于防火墻一般只開(kāi)放了幾個(gè)端口,對(duì)Oracle數(shù)據(jù)庫(kù)只開(kāi)放了1521端口,這樣在客戶端進(jìn)行第二次連接時(shí),不能通過(guò)防火墻,導(dǎo)致連接數(shù)據(jù)庫(kù)失敗。
值得慶幸的是,只有Windows平臺(tái)上的9i及以下版本的Oracle才會(huì)有這個(gè)問(wèn)題。Oracle在Linux以及Unix平臺(tái)下,多個(gè)進(jìn)程間可以對(duì)端口進(jìn)行復(fù)用,Oracle Server Process仍然使用的是跟監(jiān)聽(tīng)進(jìn)程一個(gè)端口(1521)。通過(guò)在linux使用strace跟蹤客戶端連接數(shù)據(jù)庫(kù)的過(guò)程可以發(fā)現(xiàn),客戶端只連接了一次,并沒(méi)有進(jìn)行第二次連接,與上面描述的流程相比已經(jīng)發(fā)生了變化。在Windows平臺(tái)上,10g及以上版本的庫(kù),也同樣利用端口復(fù)用,避免了這樣的問(wèn)題。
那么Windows上運(yùn)行的Oracle 9i怎么解決這個(gè)問(wèn)題呢?答案很簡(jiǎn)單,在Windows注冊(cè)表的\HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOMEn(這里n指Oracle Home的序號(hào),只有一個(gè)Oracle Home時(shí)是0)鍵下面增加一項(xiàng)USE_SHARED_SOCKET,其值為TRUE。然后重啟監(jiān)聽(tīng)及Oracle服務(wù)(注意要重啟Oracle的服務(wù),而不僅僅是重啟數(shù)據(jù)庫(kù)),就可以解決此問(wèn)題。實(shí)際上10g就是默認(rèn)USE_SHARED_SOCKET為TRUE。
對(duì)于這種問(wèn)題,或者是讓防火墻打開(kāi)針對(duì)數(shù)據(jù)庫(kù)主機(jī)的所有端口訪問(wèn),也能解決。但是這種方案往往會(huì)被負(fù)責(zé)安全的人否決。
下面這個(gè)由防火墻導(dǎo)致的問(wèn)題,就相對(duì)復(fù)雜一點(diǎn)了。
某個(gè)應(yīng)用經(jīng)常報(bào)ORA-3113錯(cuò)誤,檢查發(fā)現(xiàn)ORA-3113來(lái)源于數(shù)據(jù)庫(kù)的一個(gè)db link。為了方便下面的描述,將應(yīng)用直接連接的數(shù)據(jù)庫(kù)稱為DB_A,DB_A通過(guò)db link連接的對(duì)端的數(shù)據(jù)庫(kù)稱為DB_B。在DB_B主機(jī)上沒(méi)有發(fā)現(xiàn)任何有關(guān)的trace和日志,應(yīng)用執(zhí)行的SQL也是非常簡(jiǎn)單的SELECT語(yǔ)句,返回的數(shù)據(jù)量也不大。但出錯(cuò)的語(yǔ)句并不是固定的某一個(gè)SQL。在應(yīng)用連接的數(shù)據(jù)庫(kù)DB_A上做ORA-3113 error stack的trace,也沒(méi)有發(fā)現(xiàn)有價(jià)值的東西。
導(dǎo)致ORA-3113錯(cuò)誤的原因很多。大家可以參考ITPUB上的一篇貼子《ORA-03113錯(cuò)誤分析》。
在這個(gè)ORA-3113錯(cuò)誤的問(wèn)題中,數(shù)據(jù)庫(kù)DB_B沒(méi)有任何日志,出現(xiàn)這種情況的一個(gè)很可能的原因是,DB_B上的Server Process已經(jīng)中止,但又不是在執(zhí)行SQL過(guò)程中出錯(cuò)異常中止了,比如被KILL掉,網(wǎng)絡(luò)連接中斷等。被KILL掉這個(gè)原因,首先被排除,因?yàn)檫@個(gè)錯(cuò)誤出現(xiàn)得很多,每天都有。詢問(wèn)維護(hù)人員,稱也沒(méi)有進(jìn)行過(guò)KILL操作。那么最大的可能性應(yīng)該是網(wǎng)絡(luò)了。順著這條線索,我們?cè)?/span>DB_A上用netstat -na命令檢查到DB_B的網(wǎng)絡(luò)連接,與DB_B中v$session中的會(huì)話進(jìn)行比較,發(fā)現(xiàn)DB_A連接到DB_B的數(shù)據(jù)庫(kù)會(huì)話,比netstat 命令看到的網(wǎng)絡(luò)連接數(shù)少得多。
這是一個(gè)重大的突破。首先要懷疑的是防火墻。因?yàn)榉阑饓?dǎo)致Oracle連接異常的情況非常多。訪問(wèn)數(shù)據(jù)庫(kù)的DBA,這兩個(gè)數(shù)據(jù)庫(kù)分別在不同的業(yè)務(wù)網(wǎng)絡(luò)中,中間使用了Cisco的防火墻。請(qǐng)防火墻維護(hù)工程師檢查防火墻的設(shè)置,發(fā)現(xiàn)防火墻設(shè)置了TCP連接超時(shí)(這個(gè)術(shù)語(yǔ)是防火墻工程師告訴給我的,實(shí)際上我個(gè)人認(rèn)為這個(gè)術(shù)語(yǔ)字面含義跟其實(shí)際的作用相差較大)設(shè)置為1小時(shí)。也就是,對(duì)于通過(guò)防火墻的所有TCP連接,如果在1小時(shí)內(nèi)沒(méi)有任何活動(dòng),就會(huì)被防火墻拆除,這樣就會(huì)導(dǎo)致連接中斷。在拆除連接時(shí),也不會(huì)向連接的兩端發(fā)送任何數(shù)據(jù)來(lái)通知連接已經(jīng)拆除。
而出問(wèn)題的業(yè)務(wù)系統(tǒng),使用的高峰期是在正常的工作時(shí)間內(nèi),最高時(shí)會(huì)導(dǎo)致DB_A會(huì)產(chǎn)生數(shù)十個(gè)連接到DB_B。但是在業(yè)務(wù)低谷期或經(jīng)過(guò)一個(gè)晚上,防火墻將拆除大部分甚至是所有的連接。而下一次使用時(shí),應(yīng)用通過(guò)連接池選擇DB_A中的一個(gè)會(huì)話,這個(gè)會(huì)話的db link之前已經(jīng)連接到DB_B,但是網(wǎng)絡(luò)連接已經(jīng)被防火墻拆除,但是這個(gè)會(huì)話并不知道,仍然會(huì)認(rèn)為這個(gè)連接有效,結(jié)果試圖向DB_B提交SQL時(shí),就出現(xiàn)了ORA-3113錯(cuò)誤。
實(shí)際上,很多使用網(wǎng)絡(luò)連接的應(yīng)用,可以使用稱之為KeepAlive的特性,來(lái)保持TCP連接的活動(dòng)性。在打開(kāi)一個(gè)連接時(shí),通過(guò)setsockopt函數(shù),設(shè)置socket為SO_KEEPALIVE,這樣,在OS層,如果一個(gè)TCP連接在指定的時(shí)間內(nèi)沒(méi)有活動(dòng),會(huì)發(fā)送一個(gè)探測(cè)包到連接的對(duì)端,檢測(cè)連接的對(duì)端是否仍然存在。如果這個(gè)時(shí)間小于防火墻中設(shè)置的“超時(shí)”時(shí)間,防火墻就會(huì)檢查到連接中仍然有數(shù)據(jù),就不會(huì)斷開(kāi)這個(gè)連接。
操作系統(tǒng)中keep alive的相關(guān)設(shè)置,不同的系統(tǒng)有不同的設(shè)置方法。比如在Linux中,在sysctl中設(shè)置net.ipv4.tcp_keepalive_time = 120,表示探測(cè)時(shí)間為120秒,即2分鐘。在AIX中,通過(guò)no命令將tcp_keepidle參數(shù)設(shè)置為240,表示探測(cè)時(shí)間為120秒。注意AIX中這個(gè)參數(shù)的單位是1/2秒,而在Linux中是1秒。
還好Oracle提供了類似的機(jī)制。也就是DCD(Dead Conneciton Detection)。在$ORACLE_HOME/network/admin/sqlnet.ora文件中增加如下一行:
expire_time=NNN
這里NNN為分鐘數(shù),Oracle數(shù)據(jù)庫(kù)會(huì)在會(huì)話IDLE時(shí)間超過(guò)這個(gè)指定的時(shí)間時(shí),檢測(cè)這個(gè)會(huì)話的對(duì)端(即客戶端)是否還有效。避免客戶端由于異常退出,導(dǎo)致會(huì)話一直存在。
因此,我們可以通過(guò)在DB_B數(shù)據(jù)庫(kù)中的sqlnet.ora文件中設(shè)置expire_time來(lái)解決上面提到的ORA-3113問(wèn)題。
責(zé)任編輯:和碩涵
免責(zé)聲明:本文僅代表作者個(gè)人觀點(diǎn),與本站無(wú)關(guān)。其原創(chuàng)性以及文中陳述文字和內(nèi)容未經(jīng)本站證實(shí),對(duì)本文以及其中全部或者部分內(nèi)容、文字的真實(shí)性、完整性、及時(shí)性本站不作任何保證或承諾,請(qǐng)讀者僅作參考,并請(qǐng)自行核實(shí)相關(guān)內(nèi)容。
我要收藏
個(gè)贊
-
發(fā)電電力輔助服務(wù)營(yíng)銷決策模型
2019-06-24電力輔助服務(wù)營(yíng)銷 -
電力線路安全工作的組織措施和技術(shù)措施分別是什么?
-
兩會(huì)保電進(jìn)行時(shí)丨陜西電力部署6項(xiàng)重點(diǎn)任務(wù)
-
電力線路安全工作的組織措施和技術(shù)措施分別是什么?
-
兩會(huì)保電進(jìn)行時(shí)丨陜西電力部署6項(xiàng)重點(diǎn)任務(wù)
-
山東特高壓首次完成帶電消缺 確保電力安全穩(wěn)定迎峰度冬
-
發(fā)電電力輔助服務(wù)營(yíng)銷決策模型
2019-06-24電力輔助服務(wù)營(yíng)銷 -
繞過(guò)安卓SSL驗(yàn)證證書的四種方式
-
網(wǎng)絡(luò)何以可能
2017-02-24網(wǎng)絡(luò)
-
Windows 10首發(fā) 四大安全提升
-
超級(jí)安卓漏洞 “寄生獸”影響數(shù)千萬(wàn)手機(jī)應(yīng)用
-
航空公司首出現(xiàn)操作系統(tǒng)被黑
2015-06-23航空公司
-
“企業(yè)應(yīng)急響應(yīng)和反滲透”之真實(shí)案例分析
-
攜程恢復(fù)正常 安全,我們準(zhǔn)備好了嗎?
2015-05-29攜程 -
一張圖讀懂《2014年消費(fèi)者個(gè)人信息網(wǎng)絡(luò)安全報(bào)告》