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分鐘內被清掉。不再有連線進不去的問題出現!
留言