Oracle 11g R2 突然無法連入事件 (CLOSE_WAIT, TIME_WAIT)

 昨日我們一台Oracle 11g主機突然無法連入, 檢查後發現用SSH連入主機正常, 在主機上存取Oracle也都正常, 主機CPU, 記憶體, HD用量也都正常。只有透過網路存取Oracle的連線變得很難連上, 有時等很久之後可以連上。同事直接重開該台主機(shutdown, reboot)後, 就可以正常連上, 但沒多久又發現同樣連不上的情況!

我將listener 關下, 再打開後, 也一樣正常一下子, 然後就又連不上了。同事發現listener log檔已經非常大, 決定將log檔copy走, 刪除, 讓log檔重新開始。但是重開listener後, 情況一樣沒改善! 此時, listener log檔內可以看到一些錯誤訊息:

26-DEC-2023 12:02:54 * (CONNECT_DATA=(SERVICE_NAME=orcl)(CID=(PROGRAM=c:\windows\system32\inetsrv\w3wp.exe)(HOST=xxxx

)(USER=NETWORK?SERVICE))) * (ADDRESS=(PROTOCOL=tcp)(HOST=10.xx.xx.xx)(PORT=1234)) * establish * orcl * 12518

TNS-12518: TNS:listener could not hand off client connection

 TNS-12547: TNS:lost contact

  TNS-12560: TNS:protocol adapter error

   TNS-00517: Lost contact

    Linux Error: 32: Broken pipe

使用netstat -ant, netstat -anp | grep 1521 或者lsof -i:1521查看會發現有很多TCP/IP連線的狀態一直都呈現TIME_WAIT, CLOSE_WAIT之類的的不正常狀態, 而且很多都不會消失, 還愈來愈多!

tcp        0      0 127.0.0.1:62333             127.0.0.1:1521              ESTABLISHED 4316/ora_pmon_orcl

tcp        0      0 :::1521                     :::*                        LISTEN      15722/tnslsnr

tcp        0      0 ::ffff:127.0.0.1:1521       ::ffff:127.0.0.1:46823      TIME_WAIT   -

tcp        0      0 ::ffff:127.0.0.1:56882      ::ffff:127.0.0.1:1521       ESTABLISHED 9781/java

tcp        0      0 ::ffff:127.0.0.1:1521       ::ffff:127.0.0.1:56882      ESTABLISHED 16245/oracleorcl

tcp        0      0 ::ffff:127.0.0.1:1521       ::ffff:127.0.0.1:56880      ESTABLISHED 16241/oracleorcl

tcp        0      0 ::ffff:127.0.0.1:1521       ::ffff:127.0.0.1:46824      TIME_WAIT   -

tcp        0      0 ::ffff:127.0.0.1:1521       ::ffff:127.0.0.1:56881      ESTABLISHED 16243/oracleorcl


懷疑是tnslsnr出了問題, 找了一下網路上其他人相似的情況, 發現大陸的朋友有提到:https://blog.csdn.net/starshine/article/details/16881859, 他的解決方法看來也只是關掉tnslsnr, 再重新打開, 和我們唯一的不同是他用kill指令把tnslsnr process kill掉, 其他都一樣。不過, 這可能也是一個重點, 也許kill process才能完全把佔用的TCP/IP連線都清乾淨! 

另一位朋友https://medium.com/@brad_24220/time-wait-mitigating-tcp-ip-connection-exhaustion-c1a18080dc70的方法比較有意思, 他在/etc/sysctl.conf檔加入了一些設定(針對Oracle Linux 7/8):


net.netfilter.nf_conntrack_tcp_timeout_time_wait=1
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_fin_timeout=1

他說: "TIME_WAIT是TCP / IP堆棧中令人難以置信的部分,它使連接一直存在,直到客戶端正確關閉連接為止。但是,在某些情況下,客戶端無法正確或有效地關閉連接。這可能導致TIME_WAIT狀態下的TCP連接持續存在,直到操作系統清除它們為止。對於繁忙的系統,這可能會導致主機拒絕服務,因為所有可用的連接都綁在TIME_WAIT狀態下。"

使用vi將以上設定加入至/etc/sysctl.conf檔, 然後下 sysctl -p 指令, 我發現系統只接受後面2行, 第一行net.netfilter.nf_conntrack_tcp_timeout_time_wait=1不被接受, (可能是我的Linux版本較舊!) 將其mark掉 (#) 存檔, 再下一次 sysctl -p, 確定沒問題後, 去kill tnslsnr process, 再下lsnrctl start, 問題就解決了, 觀察一陣子, 可以看到相關的TCP/IP連線出現TIME_WAIT狀態後, 都會在1分鐘內被清掉。不再有連線進不去的問題出現!


留言

這個網誌中的熱門文章

D-BUS學習筆記

Cisco Switch學習筆記: EtherChannel

Cisco Switch學習筆記: interface的封包錯誤統計