Montag, 25. Oktober 2010

Connection Pooling - eine Übersicht

Connection Pooling ist ein Thema, von dem ich eigentlich dachte, dass ich wüsste, worum es geht: Eine Anwendung schließt geöffnete SQL Server Verbindungen nicht vollständig, sondern legt sie nur schlafen. Auf diese Weise kann die nächste Verbindung schneller hergestellt werden.
So weit, so gut. Aber wie funktioniert das genau? Als ich jetzt in einem Projekt mit einer Reihe von Fragen zu diesem Thema konfrontiert wurde, musste ich feststellen, dass hinter diesem Konzept einige Details stehen, die mir nicht auf Anhieb klar waren. Ich habe die wichtigsten hier zusammengestellt:

  • Connection Pooling ist ein Feature des Clients (genauer: des Providers, s. u.), daher schweigt sich die SQL Server Dokumentation dazu auch aus ;-)
  • Es gibt einen Unterschied zwischen OLE DB Clients und ODBC Clients:
    • Bei OLE DB Clients erfolgt die Konfiguration des Connection Pooling über den Connection String (siehe unten).
    • Bei ODBC Clients erfolgt die Konfiguration über den Konfigurations-Dialog
 
  • In der .Open Methode eines Anwendungsprogramms prüft der Provider (= Datenbank-Treiber / Brücke zwischen Anwendung und Datenbank), ob bereits ein passender Connection Pool existiert.
  • Jeder Connection Pool ist bestimmt durch:
    • Connection String (alle Verbindungen in einem Connection Pool haben einen identischen Connection String)
    • Prozess (jeder Prozess macht seine eigenen Connection Pools auf)
    • Transaktionsebenen: Verbindungen, die innerhalb einer Transaktion geöffnet werden, werden einem neuen Pool zugeordnet.
  • Jede Anwendung kann beliebig viele Connection Pools öffnen – indem sie unterschiedliche Connection Strings verwendet.
  • Mit der .Open Methode wird entweder ein neuer Pool eröffnet oder eine Verbindung in einem bereits bestehenden wiederverwendet (Wiederverwendung ist das Ziel, um so die Kosten für den Verbindungsaufbau zu reduzieren.)
    • Wenn ein existierender Pool verwendet wird, sucht der Provider darin nach einer schlafenden Verbindung (dormant).
    • Falls keine schlafende Verbindung gefunden wird, erzeugt der Provider eine neue Verbindung und legt deren Handle in den Pool.
    • Wenn eine schlafende Verbindung gefunden wird, dann wird der Status der Verbindung bereinigt ("cleared"), d. h. der Status der Verbindung ist dann wieder so wie zu dem Zeitpunkt, wo sie erzeugt wurde.
    • Wenn der Prozess nach und nach mehr Verbindungen benötigt, dann wird das Erzeugen neuer Verbindungen wiederholt, bis 100 aktive Verbindungen (das ist die Default-Obergrenze) im Pool liegen.
  • Mit Aufrufen der .Close Methode durch die Anwendung wird die Verbindung als schlafend ("dormant") gekennzeichnet. Sie lieg dann bereit für die Wiederverwendung im Pool.
    • Wenn eine Verbindung länger als 4 bis 8 Minuten schlafend ist und nicht wiederverwendet wird, dann wird sie aus dem Pool gelöscht. Das wird so oft wiederholt, bis eine minimale Anzahl von Verbindungen (Standard: 0) erreicht ist.
    • Mit Beenden der Anwendung wird der Pool und alle darin enthaltenen Verbindungen gelöscht.
Das alles wird vom Provider durchgeführt. Das Verhalten bezüglich Connection Pooling wird über optionale Schlüsselworte im Connection String gesteuert:

Schlüsselwort: Pooling
Standardwert: True
Funktion: Pooling ein- oder ausschalten

Schlüsselwort: Min Pool Size
Standardwert: 0
Funktion: Untergrenze der Anzahl von Verbindungen, die ohne Rücksicht auf ihr Alter offen gehalten werden

Schlüsselwort: Max Pool Size
Standardwert: 100
Funktion: Maximale Anzahl von Verbindungen im Pool

Die typische Werte für die Anzahl aktiver und schlafender Verbindungen in einem Pool liegt - je nach Anwendung - im Bereich zwischen 10 und 20. Die Obergrenze von 100 sollte unter normalen Umständen nie erreicht werden.