PDO Pool Architektur

Dieser Artikel beschreibt das interne Design des PDO Pool. Wenn Sie eine Nutzungsanleitung suchen, siehe PDO Pool: Verbindungspool.

Zweistufige Architektur

PDO Pool besteht aus zwei Schichten:

1. PDO-Kern (pdo_pool.c) – Logik fuer die Bindung von Verbindungen an Koroutinen, Transaktionsverwaltung, Statement-Referenzzaehlung.

2. Async Pool (zend_async_pool_t) – der universelle Ressourcenpool der Async-Erweiterung. Verwaltet die Warteschlange freier Verbindungen, Limits und Healthchecks. Er weiss nichts ueber PDO – er arbeitet mit abstrakten zval-Werten.

Diese Trennung ermoeglicht die Verwendung desselben Pooling-Mechanismus fuer beliebige Ressourcen, nicht nur Datenbanken.

Komponentendiagramm

PDO Pool -- Komponenten

Template-Verbindung

Beim Erstellen eines PDO mit einem Pool wird keine echte TCP-Verbindung geoeffnet. Stattdessen wird ein Template erstellt – ein pdo_dbh_t-Objekt, das den DSN, Benutzernamen, das Passwort und eine Referenz auf den Treiber speichert. Alle echten Verbindungen werden spaeter bei Bedarf basierend auf diesem Template erstellt.

Fuer das Template wird db_handle_init_methods() anstelle von db_handle_factory() aufgerufen. Diese Methode setzt die Methodentabelle des Treibers (dbh->methods), erstellt aber keine TCP-Verbindung und alloziert kein driver_data.

Verbindungslebenszyklus

Verbindungslebenszyklus im Pool

Erstellen einer Verbindung aus dem Pool (Sequenz)

Erstellen einer Verbindung aus dem Pool

Interne API

pdo_pool.c – Oeffentliche Funktionen

Funktion Zweck
pdo_pool_create() Erstellt einen Pool fuer pdo_dbh_t basierend auf Konstruktorattributen
pdo_pool_destroy() Gibt alle Verbindungen frei, schliesst den Pool, leert die Hashtabelle
pdo_pool_acquire_conn() Gibt eine Verbindung fuer die aktuelle Koroutine zurueck (Wiederverwendung oder Acquire)
pdo_pool_peek_conn() Gibt die gebundene Verbindung ohne Acquire zurueck (NULL wenn keine)
pdo_pool_maybe_release() Gibt die Verbindung an den Pool zurueck, wenn keine Transaktion oder Statements
pdo_pool_get_wrapper() Gibt das Async\Pool PHP-Objekt fuer die getPool()-Methode zurueck

pdo_pool.c – Interne Callbacks

Callback Wann aufgerufen
pdo_pool_factory() Pool benoetigt eine neue Verbindung (Acquire bei leerem Pool)
pdo_pool_destructor() Pool zerstoert eine Verbindung (beim Schliessen oder Eviction)
pdo_pool_healthcheck() Periodische Pruefung – lebt die Verbindung noch?
pdo_pool_before_release() Vor der Rueckgabe an den Pool – uncommitted Transaktionen zurueckrollen
pdo_pool_free_conn() Schliesst die Treiberverbindung, gibt Speicher frei

Bindung an eine Koroutine

Verbindungen werden ueber eine pool_connections-Hashtabelle an Koroutinen gebunden, wobei der Schluessel die Koroutinenkennung und der Wert ein Zeiger auf pdo_dbh_t ist.

Die Koroutinenkennung wird von der Funktion pdo_pool_coro_key() berechnet:

Bereinigung bei Koroutinen-Abschluss

Wenn eine Verbindung an eine Koroutine gebunden wird, wird ein pdo_pool_cleanup_callback ueber coro->event.add_callback() registriert. Wenn die Koroutine abschliesst (normal oder mit einem Fehler), gibt der Callback die Verbindung automatisch an den Pool zurueck. Dies garantiert keine Verbindungslecks, selbst bei unbehandelten Ausnahmen.

Pinning: Verbindungssperrung

Eine Verbindung ist an eine Koroutine gepinnt und wird nicht an den Pool zurueckgegeben, wenn mindestens eine Bedingung erfuellt ist:

Der Refcount wird beim Erstellen eines Statements inkrementiert und beim Zerstoeren dekrementiert. Wenn beide Bedingungen erfuellt sind, gibt pdo_pool_maybe_release() die Verbindung an den Pool zurueck.

Zugangsdatenverwaltung in der Factory

Beim Erstellen einer neuen Verbindung kopiert pdo_pool_factory() die DSN-, Benutzernamen- und Passwort-Strings vom Template ueber estrdup(). Dies ist notwendig, da Treiber diese Felder waehrend db_handle_factory() mutieren koennen:

Nach einem erfolgreichen db_handle_factory()-Aufruf werden die Kopien ueber efree() freigegeben. Bei Fehlern erfolgt die Freigabe ueber pdo_pool_free_conn(), die auch vom Destruktor des Pools verwendet wird.

Inkompatibilitaet mit persistenten Verbindungen

Persistente Verbindungen (PDO::ATTR_PERSISTENT) sind mit dem Pool inkompatibel. Eine persistente Verbindung ist an den Prozess gebunden und ueberlebt Anfragen, waehrend der Pool Verbindungen auf Anfrageebene mit automatischem Lebenszyklus-Management erstellt. Der Versuch, beide Attribute gleichzeitig zu aktivieren, fuehrt zu einem Fehler.

Was kommt als Naechstes?