2017-07-19 5 views
1

Ein in C# Oracle-Client geschriebenes Programm, das "Connection leak" aufweist und nicht alle Datenbankverbindungen schließt. Nach einiger Zeit kann es keine Verbindung mehr zur Datenbank herstellen, da zu viele offene Verbindungen bestehen.Der beste Weg, Oracle Verbindungsleck zu erkennen?

Ich schrieb die folgende Hilfsfunktion (recht expansive):

 private static int tryFindConnCount(){ 
      var connstk = new Stack<Oracle.ManagedDataAccess.Client.OracleConnection>(); 
      try 
      { 
       for (var i = 0; i < 10000; ++i) 
       { 
        var conn = new Oracle.ManagedDataAccess.Client.OracleConnection(
         myDatabaseConnection); 
        conn.Open(); 
        connstk.Push(conn); 
       }     
      } 
      catch(Exception e) 
      { 
       foreach (var conn in connstk) 
       { 
        conn.Close(); 
       } 

      } 
      return connstk.Count; 
     } 

Hier ist der Code in einem Testfall, dass die oben verwendet:

  var co = tryFindConnCount(); 
      CodeThatMayLeakConnection(); 
      var cn = tryFindConnCount(); 

      Assert.That(cn, Is.EqaulTo(co)); 

Es half mir mindestens einen Fall zu identifizieren das haben Verbindungsleck.

Das Problem von tryFindConnCount ist, dass es nie in der Produktion verwendet werden sollte. Und ich denke, es sollte einen Weg geben, den gleichen Wert viel billiger zu erhalten.

Wie kann ich dies im Code tun, damit ich diesen Wert in der Produktion überwachen kann?

+1

Sie können die Oracle-Datenbank abfragen, um die Gesamtzahl der Verbindungen von Verbindungen zu erhalten, die von diesem Programm stammen. Zum Beispiel: Wählen Sie Anzahl (*) von gv $ Sitzung wo Maschine = 'XXXXX' und Benutzername = 'YYYYY' und Programm = 'ZZZZZ'; – ivanzg

+0

Sie benötigen nur einige spezifische Werte, die diese Verbindungen eindeutig identifizieren, wie zum Beispiel die Maschine, von der sie stammt -> "server.123.local.com", DB-Benutzername, mit dem die Verbindungen in die Datenbank gelangen und vielleicht den Programmnamen wie "clientprogram1 "oder ein anderes Attribut. – ivanzg

Antwort

2

Der Versuch, Orte zu finden, an denen Verbindungen nicht geschlossen sind, ist eine schwierige Aufgabe.

Wenn Sie das Programm verlassen und vergessen, die Verbindung zu schließen, wird die letzte SQL, die ausgeführt wurde, in der Spalte SQL_ID in v $ session (gv $ session für RAC) gespeichert. Sie können v $ session für Leerlauf-/Dead-Sitzungen suchen. Sie können dann v $ sql verwenden, um den SQL-Text zu finden, der Ihnen vielleicht mehr darüber verrät, was zuletzt gemacht wurde. Dadurch erhalten Sie einen Hinweis, wo Sie in Ihrem Code suchen können.

select a.sid, a.username, a.program, a.machine, a.sql_id, b.sql_fulltext 
    from v$session a, v$sql b 
where b.sql_id(+) = a.sql_id 
    and a.username is not null -- filter system processes, maybe filter more stuff 
; 
1

Sie können Oracle DB in der Ansicht "gv $ session" abfragen, um die benötigten Informationen zu erhalten. Mit einer Abfrage dieser Sicht können Sie die DB zyklisch alle 10-15 Minuten auf eine Anzahl von Verbindungen von diesem Programm überwachen.

Beispiel Abfrage unter:

select count(*) 
from gv$session 
where machine = 'XXXXX' 
and username = 'YYYYY' 
and program = 'ZZZZZ'; 

Sie nur Werte benötigen, die eindeutig diese Verbindungen wie aus denen zum Beispiel Maschine identifizieren die Verbindungen stammen.

Auch die Abfrage ist sehr leicht und fügt keinen zusätzlichen Leistungsaufwand hinzu.

Verwandte Themen