SQL Developer PL/SQL 腳本在執行一定時間後無法通過 OpenVPN 顯示輸出
問題:
當我嘗試在我的 Oracle 19c 數據庫上通過 OpenVPN 執行收集統計資訊時,如果執行超過一定時間,SQL Developer 不會返回典型的“PL/SQL 過程已成功完成”消息。
顯然,連接會在一段時間後掛起,我要麼需要斷開與 OpenVPN 的連接,要麼需要在 Windows 任務管理器中殺死 SQL Developer 以關閉它。
我的 Oracle 19c 數據庫和 OpenVPN 伺服器位於不同的雲提供商上。
在此數據庫上執行收集統計資訊通常需要大約半小時。
我檢查了什麼:
- OpenVPN 伺服器上的 Iptables 和 OpenVPN 日誌或 Oracle 19c 伺服器上的偵聽器和警報日誌上沒有任何異常。
- net.ipv4.tcp_keepalive_time 和 net.netfilter.nf_conntrack_tcp_timeout_established 在兩台機器上都設置為它們的預設值 7200(2 小時)和 432000(5 天)。
- 如果我以系統身份連接到數據庫並執行:
從 v 中選擇 x.sid、x.serial#、x.username、x.status、x.osuser、x.machine、x.program、x.event、x.state、sql.sql_text $ sqlarea sql, v $ 會話 x 其中 x.sql_hash_value = sql.hash_value 和 x.sql_address = sql.address 和 x.username = ‘myuser’;
大約半小時後,我注意到收集統計資訊的會話處於非活動狀態。所以我假設收集統計資訊確實執行並成功完成,但只是不返回上述輸出消息。
我嘗試了什麼:
- 在同一實例中的較小數據庫上,通過 OpenVPN 執行收集統計資訊會返回上述成功消息。這個大約需要 10 分鐘。
- 通過將我的 IP 地址添加到雲提供商的防火牆並執行收集統計資訊來直接(不使用 OpenVPN)連接到數據庫也會返回上述成功消息。
- 在 Oracle 19c 伺服器上生成 SSH 公鑰/私鑰對並在 SQL Developer 上使用 SSH 主機,但連接非常不穩定/總是在重置。
- 設置 Dante 代理伺服器。顯然,SQL Developer 只能使用某種特殊的代理伺服器。
- 使用 StrongSwan 設置 IPSEC VPN。由於某種原因,我的 Windows 10 無法與其建立連接。
首先,我能夠通過執行確認收集統計資訊確實成功完成:
select * from v$session_longops where opname like '%Schema%' order by start_time desc;
之後,我在兩台伺服器上執行了以下 tcpdump 命令:
tcpdump -i eth0 -A "(src <myipaddress> or src <myoracle19caddress> or dst <myipaddress> or dst <myoracle19caddress>) and not port ssh and not port openvpn and not icmp" (OpenVPN Server) tcpdump -i eth0 -A "(src <myipaddress> or src <myopenvpnserveraddress> or dst <myipaddress> or dst <myopenvpnserveraddress>) and not port ssh and not icmp" (Oracle 19c Server)
並發現 Oracle 19c 伺服器確實發送了成功消息,但 OpenVPN 伺服器從未收到它。
在各個站點上進行了一些探勘之後,我發現我誤解了 net.ipv4.tcp_keepalive_time 的實際作用。
這意味著
$$ by default $$keepalive 常式在發送第一個 keepalive 探測之前等待兩個小時(7200 秒) ,然後每 75 秒重新發送一次。
之後,我發現了託管 OpenVPN 伺服器的雲提供商的網路配置。
空閒連接
$$ … $$對具有連接概念的 IP 協議實施 10 分鐘連接跟踪。這意味著只要在過去 10 分鐘內為該連接發送或接收了至少一個數據包,就允許與已建立的連接關聯的入站數據包。如果 10 分鐘或更長時間沒有發送或接收連接的數據包,則刪除空閒連接的跟踪條目。刪除連接的跟踪條目後,$$ … $$在至少發送一個新的出站數據包之前,不允許額外的入站數據包。此連接跟踪適用於所有源和目標 - 內部和外部 IP 地址。
有了這些新資訊,我通過在 Oracle 19c 伺服器上執行以下命令將 keepalive 時間設置為小於 10 分鐘的值,從而繞過了這個限制:
sysctl -w net.ipv4.tcp_keepalive_time=300 net.ipv4.tcp_keepalive_intvl=60 net.ipv4.tcp_keepalive_probes=5
並通過將它們保存到 /etc/sysctl.conf 使這些更改永久化。
最後,SQL Developer 收到成功消息並關閉連接。