Twenty-five minutes of useful database work produces almost no output, and from every device in the path that flow looks idle. Idle state is exactly what gets collected. The report afterwards is always the same shape: the query was running, then the session vanished, and the result never arrived.

Four checks decide whether a quiet session survives, and they run from the socket outward. Do them in order, because each one assumes the previous layer is doing its job.

Which flow goes quiet

The connection that matters is the one carrying the database traffic, identified by its own addresses and ports. Nothing else refreshes it. A ping to a gateway, a second SQL connection from the same host, and the tunnel's own heartbeat are separate flows with separate state on every device that tracks them.

ss -tio dst 10.60.4.20
sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_intvl net.ipv4.tcp_keepalive_probes

The socket listing shows timers and queue state for the live connection, which is more informative than a reachability test. The sysctl values are the kernel defaults for keepalive behaviour, and the next section explains why they may never apply to your session. A default that never fires is indistinguishable from no default at all.

Write down the addresses, the ports and the interface the connection uses. When a session dies, those details are what let you ask the right device what it did, rather than asking whether the network was up.

Does the idle policy expire or limit

Two policies produce the same symptom and need opposite responses. An idle timeout removes state that qualifying traffic could have refreshed, and a keepalive can prevent it. An absolute session limit removes the flow after a fixed duration regardless of activity, and no keepalive changes that.

Ask the owner of each intermediary which one it implements. A firewall, a NAT device, a load balancer and a cloud gateway can all hold state, and they do not have to agree. The narrowest one sets the deadline you have to beat.

This distinction also tells you when to stop tuning. If the policy is an absolute limit, the correct fix is a shorter unit of work, a resumable job, or an approved exception, and the check below will simply confirm that keepalives made no difference.

The socket switch behind the Linux defaults

Keepalive is opt-in per socket. The kernel defaults describe how probes behave once a socket has enabled the mechanism, and they do not enable it for existing connections. An application that never asks for it gets no probes, whatever the sysctl values say.

That is why raising the numbers alone changes nothing for a database client. The client library or the application has to enable the mechanism, and where the stack exposes per-connection controls, a scoped setting beats a host-wide change that affects unrelated services.

The first-probe interval is also not a query timeout. A healthy connection stays quiet between probes, and a dead peer is recognized according to the probe interval and count. Reading those three values as one timeout is how people arrive at settings that detect failure either far too late or far too eagerly. They control detection, not application patience.

EXPIRE_TIME is a database setting, not a network fix

Oracle Net offers its own liveness mechanism, configured in the effective profile for the process rather than in an arbitrary file that happens to have a similar name. The value is expressed in minutes.

SQLNET.EXPIRE_TIME = 5

Its primary purpose is server-side detection of dead connections, and on platforms supporting the enhanced model it also tunes TCP keepalive behaviour for those connections. That is a useful property: it means the database layer can arrange for probes without asking the client application to change.

The illustrative value above is a coordinated choice against an assumed deadline, not a recommendation. The documented general guidance is a longer interval, and the right number depends on the installed implementation, the probe overhead you accept and the actual refresh rules on the path. Put the setting in the profile that the relevant process reads, and confirm the process picked it up. Oracle documents the profile locations and the detection behaviour in its parameter reference.

Test the quiet interval, then plan recovery

Exercise a fresh permitted connection through a quiet period longer than the deadline you are trying to beat, and watch for the liveness traffic and the application result. Do not capture payload content you do not need; timers and connection state answer the question.

ss -tio dst 10.60.4.20
# after the quiet interval, same command
ls -l "$ORACLE_HOME/network/admin/sqlnet.ora"

If the session still disappears, the deadline belongs to a device you have not asked yet, or the policy is an absolute limit. If it survives, record which layer changed so the next quiet operation does not repeat the investigation.

Finally, decide what happens when the connection does drop, because liveness checks reduce the frequency and never remove the possibility. Establish the database operation's recorded outcome before resubmitting it: losing the reply proves nothing about whether the work committed. For anything that must survive a laptop closing or a tunnel restart, a server-owned job with a durable result is the stronger design, and a keepalive is not a scheduler.

Akụkọ ndị metụtara ya