Oracle8: TNS Retry Count

Verbindungen zu unserer Oracle Datenbank werden durch eine Firewall geleitet, was auch grundsätzlich funktioniert. Nun gibt es eine Reihe von Situationen, in denen die Firewall Verbindungen dropped, d.h. nicht mehr weiterleitet. Auf Netzwerkebene sieht es dann so aus, dass die tcp-Verbindung zur Datenbank erhalten bleibt, gesendete Daten aber durch die Firewall nicht weiter zum Server geleitet werden. In einem Snoop habe ich beobachtet, dass ein Request (ausführen eines SQL Statement) erfolgreich vom client versandt und von der Firewall geACKt wird. Der Oracle Client wartet nun einige Zeit auf die Antwort von der Datenbank und führt nach ca. 2 Minuten einen Retry auf TNS Ebende durch. Dieser Vorgang wiederholt sich über einen Zeitraum von 8 bis 10 Minuten, dann wird eine Fehler zur aufrufenden Funktion zurückgemeldet.

Ich suche nun eine Möglichkeit, die Zeitspanne bis zu einem Retry und die Anzahl der Retries des TNS Protokolls zu konfigurieren. Ich habe eine Option FAILOVER gefunden, die in tnsnames.ora diese Parameter für den Verbindungsaufbau konfiguriert. Nach meinem Verständnis werden diese Parameter aber NUR für den Verbindungsauf verwendet. Gibt es noch andere Möglichkeiten, die von mir gesuchten Parameter zu konfigurieren?
Gibt es andere Alternativen, etwa Client Parameter?

Mein Ziel ist das Erreichen einer kleineren Reaktionszeit, d.h. die Applikation hängt nicht mehr 10 Minuten sondern nur noch 2 Minuten bis zum Erkennen des Fehlers und führt dann einen Reconnect aus.

Markus

hi!

ohne es jetzt zu wissen oder nachgeschaut zu haben:
sqlnet.ora?

hier bzw. in irgendeinem anderen *net*-file im oracle-(net80/network-)verzeichnis könnte _etwas_ einzurichten sein

aber warum das problem nicht an der wurzel packen und die firewall so umkonfigurieren, das die „guten“ pakete durchkommen und wirklich nur die „bösen“ draußenbleiben?

grüße,
tomh

hi!

ohne es jetzt zu wissen oder nachgeschaut zu haben:
sqlnet.ora?

Hier habe ich nichts finden können, was im Zusammenhang mit dem Retry steht. Einzig FAILOVER in tnsnames.ora mit den Parametern RETRY und TIMEOUT haben Einfluß, lt.- Doku aber nur beim Verbindungsaufbau.

aber warum das problem nicht an der wurzel packen und die
firewall so umkonfigurieren, das die „guten“ pakete
durchkommen und wirklich nur die „bösen“ draußenbleiben?

Weil die Firewall bei einem Kunden steht, und die Verbindung von einem unsicheren Netz auf den Server im sicheren Netz erfolgt. Ein potentieller Angreifer kann das unsichere System übernehmen und ggf. von hier aus die DB kontaktieren oder Datenbankverbindungen hijacken.
In diesem Zusammenhang gibt es keine Regeln, wie gute oder böse Pakete aussehen. Sie kommen alle vom selben Host.
Mir wäre auch schon geholfen, wenn die Firewall die Verbindung nicht nur droppen, sondern die darunterliegende tcp-Verbindung einfach zurücksetzen würde. Da es sich um eine Hardware-Firewall handelt, ist das leider nicht möglich. Ein Upgrade auf eine bessere Firewall ist auch nicht akzeptabel, da hiermit wesentlich höhere Kosten verbunden sind.

Gruß Markus

Hallo Markus!

Ich bin etwas skeptisch, ob ich dir da helfen kann, aber vielleicht geht’s ja doch… Dazu bräuchte ich aber eine grundlegende Info: Wie verbindet ihr euch durch die FW hindurch? Shared Socket? SQL*Net-Proxy auf der Firewall?

Gruß
Martin

Ich bin etwas skeptisch, ob ich dir da helfen kann, aber
vielleicht geht’s ja doch… Dazu bräuchte ich aber eine
grundlegende Info: Wie verbindet ihr euch durch die FW
hindurch? Shared Socket? SQL*Net-Proxy auf der Firewall?

Meines wissens ist die Verbindung transparent, d.h. der DB-Client sieht die Firewall gar nicht. Die Verbindung wird aus Sicht des Clients direkt zum Datenbank-Server aufgebaut, die Firewall ist der man-in-the-middle. Die Kommunikation verwendest net8/protocol=tcp, womit dann auch Sockets verwendet werden. Im Einsatz ist der Dedicated Server, Server-Ports sind auf einen Bereich konfiguriert, der von der Firewall durchgelassen wird. MultiThreadedServer kommt nicht in Frage.

Ich glaube aber kaum, dass dich diese Infos weiterbringen. Laut Netzwerktraces hat der Client seinen Request geschickt und vom Netzwerkstack auf tcp-Ebene ein ACK erhalten. Aus Sicht des Clients sind die Daten nun beim Server angekommen, er wartet daher nun auf (Applikations-Ebene/TNS) auf eine Antwort. Da die Antwort erst gar nicht beim Client ankommt, die Firewall leitet die Daten nicht weiter, wird nach n-Sekunden ein Retry ausgeführt.

Gruß Markus

Hallo Markus!

So wie du das beschrieben hast kann ich mir nicht vorstellen, dass das funktioniert: Mit den Serverports nehme ich an meinst du die von tnsnames.ora bzw. listener.ora. Die werden aber ausschliesslich zum Verbindungsaufbau verwendet. Das sieht in etwa so aus: Der Client schickt einen Request Login nach $PORT (idR 1521 o. 1526). Der Listener kriegt den Request und schickt nun als allererstes einen Redirect an den Client auf einen beliebigen freien Port (kann leider nicht eingeschränkt werden) - z.B. 10768. Der Client kommuniziert ab dem Zeitpunkt nicht mehr mit dem Listener sondern direkt mit der DB (etwas vereinfacht ausgedrückt), und zwar über den Port 10768. Wenn die Firewall also nicht alles über [weissichjetztnichtauswendig] offen hat kann der Client keine Verbindung zur DB aufbauen.

Dazu gibt’s zwei verschiedene Lösungen:
a) Man verwendet shared sockets, d.h. alle Clientprozesse laufen ohne den Redirect weiterhin auf dem $PORT (also den aus der tnsnames/listener). Nachteil: Wenn der Listener beendet wird sterben auch alle bestehenden Verbindungen (funktioniert mW ab Version 8.1.7.4, evtl. auch schon 8.1.7.2, jedenfalls nicht unter 8.1.7.0).

b) Die Firewall „kann“ SQL*Net und arbeitet als SQL*Net-Proxy. Hat eigentlich keine Nachteile, ausser der Tatsache, dass man eben eine FW braucht, die das auch kann.

Ich weiss, dass deine ursprüngliche Anfrage eine andere war, aber dafür gibt es meiner Ansicht nach keine Lösung, weil SQL*Net keine clientseitige dead connection detection unterstützt (zumindest laut Metalink). Dort gibt es das lediglich vom Server aus, damit Clientprozesse nicht ewig am Server hängen bleiben.

Die einzige Lösung für dein Problem - so es sich nicht umschiffen lässt - ist von mir aus gesehen die Änderung der Dauer des TCP retry/timeouts (frag mich bitte nicht, wie das geht, das ist mir schon zu weit weg von Oracle *g*). Das betrifft dann aber eben _alle_ TCP connections, und nicht nur SQL*Net.

Gruß
Martin

Die einzige Lösung für dein Problem - so es sich nicht
umschiffen lässt - ist von mir aus gesehen die Änderung der
Dauer des TCP retry/timeouts (frag mich bitte nicht, wie das
geht, das ist mir schon zu weit weg von Oracle *g*). Das
betrifft dann aber eben _alle_ TCP connections, und nicht nur
SQL*Net.

Aber genau an dieser Stelle liegt das Problem: auf der Ebene tcp gibt es keine Retries, soweit ich das gesehen habe werden die Datenpakte geACKt. Dafür gibt es nach ca. 2 Minuten einen Retry auf dem Applikationsprotokoll TNS (=net8!?), der Vorgang wiederholt sich einige male bis die Oracle Client API nach 8-10 Minuten einen Fehler signalisiert.
Ich vermute hier einen Clientseitigen Parameter, welcher Dauer und Anzahl der Retries steuert. Fragt sich nur, wie man den konfiguriert?

Markus

Hallo Markus!

Ich vermute hier einen Clientseitigen Parameter, welcher Dauer
und Anzahl der Retries steuert. Fragt sich nur, wie man den
konfiguriert?

Wie schon gesagt, laut Metalink gibt es einen solchen Parameter nicht. Oracle selbst hält sich aber in Diskussionen zu dem Thema beinahe schon auffallend zurück. Vielleicht gibt es ihn also doch, aber eben undokumentiert (so wie sie bei den character sets das internal_use einfach aus der Doku entfernt haben…). In dem Fall hilft wohl nur eine Recherche im Netz, ein kurzer Versuch meinerseits hat allerdings nichts verwertbares eingebracht.

Trotzdem: Ich meine immer noch du solltest das Problem an der Wurzel packen und die Verbindungsverluste beseitigen anstatt den Timeout (versuchen) zu ändern…

Gruß
Martin

Wie schon gesagt, laut Metalink gibt es einen solchen
Parameter nicht. Oracle selbst hält sich aber in Diskussionen
zu dem Thema beinahe schon auffallend zurück. Vielleicht gibt
es ihn also doch, aber eben undokumentiert (so wie sie bei den
character sets das internal_use einfach aus der Doku entfernt
haben…). In dem Fall hilft wohl nur eine Recherche im Netz,
ein kurzer Versuch meinerseits hat allerdings nichts
verwertbares eingebracht.

Danke für deine Mühen! Mittlerweile glaube ich nicht mehr,
dass es einen Parameter gibt.

Trotzdem: Ich meine immer noch du solltest das Problem an der
Wurzel packen und die Verbindungsverluste beseitigen anstatt
den Timeout (versuchen) zu ändern…

Das ist nur schwer möglich: meine Applikation läuft beim Kunden, der ist ein wenig paranoiod und hat alle kritsichen Punkte durch eine Firewall geschützt. Einige Stellen waren gar so kritisch, dass statt sql soap verwendet wurde.
Da es sich meines wissens um hardware Firewalls handelt, kann hier nicht viel schrauben. Da performance durch die Firewall ein wichtige Rolle spielt, fallen einige andere Optionen auch weg, wie etwa eine Linux-Firewall (die geht bei einigen hundert requests bereits in die Knie)

Gruß Markus