یکی از مشکلات رایج در محیطهایی که بین کلاینت و دیتابیس فایروال یا NAT وجود دارد، قطع شدن ارتباط سشنهای Idle بهعلت Timeout است.
برای حل این مشکل، اوراکل پارامتر SQLNET.EXPIRE_TIME
را معرفی کرده است. این پارامتر باعث میشود دیتابیس بهصورت دورهای بستههای کوچک (probe) ارسال کند تا مسیر ارتباطی همچنان فعال باقی بماند. این مکانیزم در واقع نوعی شبیهسازی TCP KeepAlive است تا فایروالها ارتباط ما را قطع نکنند.
محیط تست
-
سرور دیتابیس (VMware Workstation)
-
آدرس:
192.168.188.3
-
دیتابیس: Oracle 19c (Instance:
orcl
)
-
-
کلاینت ویندوز
-
آدرس:
192.168.188.1
-
ابزار اتصال: SQL Developer (با کاربر SYS)
-
-
شبکه: اتصال مستقیم روی پورت 1521
تنظیم پارامتر SQLNET.EXPIRE_TIME
پارامتر در فایل sqlnet.ora
در مسیر DB Home (نه Grid Home) تنظیم شد:
# $ORACLE_HOME/network/admin/sqlnet.ora
SQLNET.EXPIRE_TIME = 1
-
مقدار ۱ دقیقه صرفاً برای شبیهسازی در محیط تست انتخاب شد (در محیط واقعی معمولاً روی ۱۰ یا ۱۵ دقیقه قرار داده میشود).
-
پس از تغییر فایل، روی سرور دستور زیر اجرا شد:
lsnrctl reload
-
تا Listener تغییرات را دریافت کند.
-
توجه شود که این پارامتر فقط روی Sessionهای جدید اثر میگذارد؛ سشنهای فعال قبل از تغییر، بدون بازسازی اتصال از این مکانیزم استفاده نخواهند کرد.
مانیتورینگ با tcpdump
برای مشاهده تبادل Probe و ACK بین سرور و کلاینت، از دستور زیر با اجرا توسط کاربر root استفاده شد:
tcpdump -i ens160 host 192.168.188.1 and port 1521 -nn -vvv -X -s0
خروجی نمونه
Probe و پاسخ ACK
این خروجی بصورت خلاصه شده است و متن واقعی بیشتر از این حجم دارد
05:32:41.416996 IP 192.168.188.3.1521 > 192.168.188.1.51965: Flags [.], length 0
05:32:41.417692 IP 192.168.188.1.51965 > 192.168.188.3.1521: Flags [.], length 0
-
خط اول: سرور یک probe ارسال کرده است.
-
خط دوم: کلاینت با ACK پاسخ داده است.
-
نتیجه: ارتباط زنده است.
تکرار در بازههای بعدی
05:33:42.857052 IP 192.168.188.3.1521 > 192.168.188.1.51965: Flags [.], length 0
05:33:42.858105 IP 192.168.188.1.51965 > 192.168.188.3.1521: Flags [.], length 0
این چرخه در هر یک دقیقه تکرار میشود و Session در دیتابیس پایدار میماند.
بررسی Session در دیتابیس
با کوئری زیر Session کلاینت بررسی شد. از آنجا که با sql developer متصل شده بودم این جستجو را اجرا کردم:
select s.inst_id,
s.status,
s.sid||','||s.serial# sid_serial,
s.program,
s.osuser,
s.username,
s.machine,
s.logon_time
from gv$session s
where program like 'SQL%';
نمونه خروجی:
INST_ID | STATUS | SID_SERIAL | PROGRAM | OSUSER | USERNAME | MACHINE | LOGON_TIME |
---|---|---|---|---|---|---|---|
1 | INACTIVE | 98,60437 | SQL Developer | Vahid | SYS | vahidpc | 28-SEP-2025 05:10:54 |
جمعبندی
-
پارامتر
SQLNET.EXPIRE_TIME
باعث میشود سرور بستههای KeepAlive شبیهسازیشده ارسال کند تا فایروالها Session را قطع نکنند. -
در تست حاضر، مقدار روی ۱ دقیقه تنظیم شد تا تبادلات بهوضوح در tcpdump قابل مشاهده باشند.
-
برای اعمال تغییر، Listener با دستور
reload
بهروزرسانی شد. -
مکانیزم فقط روی سشنهای جدید اثر دارد.
-
در خروجی
tcpdump
میتوان ACKهای منظم را مشاهده کرد که نشاندهنده سلامت ارتباط است. -
در صورت قطع کلاینت، بهجای ACK، پاسخ RST یا ICMP مشاهده خواهد شد و Session خاتمه پیدا میکند.