<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/features.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'de',
  ),
  'this' => 
  array (
    0 => 'features.persistent-connections.php',
    1 => 'Persistente Datenbankverbindungen',
    2 => 'Persistente Datenbankverbindungen',
  ),
  'up' => 
  array (
    0 => 'features.php',
    1 => 'Features',
  ),
  'prev' => 
  array (
    0 => 'features.connection-handling.php',
    1 => 'Verbindungssteuerung',
  ),
  'next' => 
  array (
    0 => 'features.commandline.php',
    1 => 'Nutzung der Kommandzeile',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'de',
    'path' => 'features/persistent-connections.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="features.persistent-connections" class="chapter">
 <h1 class="title">Persistente Datenbankverbindungen</h1>


 <div class="simplesect">
  <h3 class="title">Was sind persistente Verbindungen?</h3>
  <p class="simpara">
   Persistente Verbindungen sind Verbindungen, die nach Beendigung der
   Skriptausführung nicht geschlossen werden. Wird eine persistente
   Verbindung angefordert, prüft PHP, ob bereits eine identische persistente
   Verbindung (die von einem früheren Aufruf offen geblieben ist) existiert;
   ist dies der Fall, wird sie wiederverwendet, andernfalls wird eine neue
   Verbindung aufgebaut. Eine &quot;identische&quot; Verbindung ist eine Verbindung,
   die zum gleichen Host mit demselben Benutzernamen und Passwort
   (sofern zutreffend) hergestellt wurde.
  </p>
  <p class="simpara">
   Es gibt keine Möglichkeit, eine bestimmte Verbindung anzufordern oder zu
   garantieren, ob die zurückgegebene Verbindung eine bestehende oder eine
   ganz neue ist (etwa wenn alle bestehenden Verbindungen in Verwendung sind
   oder die Anfrage von einem anderen Worker bearbeitet wird, der über einen
   eigenen Verbindungs-Pool verfügt).
  </p>
  <p class="simpara">
   Die persistenten Verbindungen von PHP können daher beispielsweise nicht
   verwendet werden, um:
  </p>
  <ul class="simplelist">
   <li>eine bestimmte Datenbanksitzung einem bestimmten Web-Benutzer zuzuweisen</li>
   <li>eine umfangreiche Transaktion über mehrere Anfragen hinweg aufzubauen</li>
   <li>eine Abfrage in einer Anfrage zu starten und die Ergebnisse in einer anderen abzurufen</li>
  </ul>
  <p class="simpara">
   Persistente Verbindungen bieten <em>keinerlei</em>
   Funktionalität, die nicht auch mit nicht-persistenten Verbindungen
   möglich wäre.
  </p>
 </div>

 <div class="simplesect" id="persistent-connections.web">
  <h3 class="title">Web-Anfragen</h3>
  <p class="simpara">
   Es gibt zwei Möglichkeiten, wie ein Webserver PHP zur Generierung von
   Webseiten einsetzen kann:
  </p>
  <p class="simpara">
   Die erste Methode ist, PHP als CGI-&quot;Wrapper&quot; zu benutzen. Wenn diese
   Methode eingesetzt wird, wird für jede Anfrage nach einer PHP-Seite vom
   Webserver eine Instanz des PHP-Interpreters gestartet und anschließend
   wieder beendet. Durch die Beendigung des Interpreters nach jeder Anfrage
   werden alle Ressourcen, auf die zugegriffen wurde (wie beispielsweise
   eine Verbindung zu einem SQL-Datenbankserver), wieder geschlossen. In
   diesem Fall erreicht man nichts, wenn man persistente Verbindungen
   benutzt - Persistenz ist in diesem Fall nicht gegeben.
  </p>
  <p class="simpara">
   Die zweite und populärste Methode ist der Einsatz von PHP-FPM oder von
   PHP als Modul in einem Multiprozess-Webserver (derzeit nur Apache).
   Solche Umgebungen haben typischerweise einen Prozess (den Elternprozess),
   der eine Reihe weiterer Prozesse (seine Kinder) koordiniert, welche die
   eigentliche Arbeit des Bereitstellens der Webseiten übernehmen. Wenn
   eine Anfrage von einem Client eingeht, wird sie an eines der Kinder
   weitergereicht, das gerade keinen anderen Client bedient. Das bedeutet,
   dass eine zweite Anfrage desselben Clients an den Server unter Umständen
   von einem anderen Kindprozess als die erste Anfrage bearbeitet wird.
   Wurde eine persistente Verbindung einmal geöffnet, kann jede danach
   vom selben Kindprozess bediente Seite die bereits aufgebaute Verbindung
   zum SQL-Server weiterverwenden.
  </p>
  <blockquote class="note"><p><strong class="note">Hinweis</strong>: 
   <p class="para">
   Die verwendete Methode lässt sich anhand des Werts von &quot;Server API&quot; in
   der Ausgabe von <span class="function"><a href="function.phpinfo.php" class="function">phpinfo()</a></span> oder anhand des Werts der
   Konstante <strong><code><a href="reserved.constants.php#constant.php-sapi">PHP_SAPI</a></code></strong>, ausgeführt über eine
   Web-Anfrage, prüfen.
   </p>
   <p class="para">
    Lautet die Server API &quot;Apache 2 Handler&quot; oder &quot;FPM/FastCGI&quot;, werden
    persistente Verbindungen über Anfragen hinweg wiederverwendet, die vom
    selben Worker bedient werden. Bei jedem anderen Wert bleiben
    persistente Verbindungen nach jeder Anfrage nicht erhalten.
   </p>
  </p></blockquote>
 </div>

 <div class="simplesect" id="persistent-connections.cli">
  <h3 class="title">Kommandozeilen-Prozesse</h3>
  <p class="simpara">
   Da PHP auf der Kommandozeile für jedes Skript einen neuen Prozess
   verwendet, werden persistente Verbindungen nicht zwischen
   Kommandozeilen-Skripten geteilt. Es bringt daher keinen Nutzen, sie in
   kurzlebigen Skripten wie Cronjobs oder einmaligen Kommandozeilenbefehlen
   einzusetzen. Sie können jedoch zum Beispiel in einem langlaufenden
   Anwendungsserver nützlich sein, der viele Anfragen oder Aufgaben bedient,
   von denen jede ihre eigene Datenbankverbindung benötigen kann.
  </p>
 </div>

 <div class="simplesect" id="persistent-connections.why">
  <h3 class="title">Wozu sie verwenden?</h3>
  <p class="simpara">
   Persistente Verbindungen sind nützlich, wenn der Aufwand zum Aufbau
   einer Verbindung zu einem SQL-Server hoch ist. Ob dieser Aufwand
   signifikant ist, hängt von vielen Faktoren ab, etwa von der Art der
   Datenbank, davon, ob sie auf demselben Rechner wie der Webserver läuft,
   und davon, wie stark dieser Rechner ausgelastet ist. Ist der
   Verbindungsaufwand hoch, können persistente Verbindungen erheblich
   helfen: Jeder Kindprozess verbindet sich nur einmal während seiner
   gesamten Lebensdauer, statt jedes Mal, wenn er eine Seite verarbeitet,
   die eine Verbindung zum SQL-Server benötigt. Das bedeutet, dass jeder
   Kindprozess, der eine persistente Verbindung öffnet, seine eigene
   Verbindung zum Server unterhält. Bei beispielsweise 20 verschiedenen
   Kindprozessen, die jeweils ein Skript ausführen, das eine persistente
   Verbindung zum SQL-Server aufbaut, ergeben sich 20 separate
   Verbindungen zu diesem Server, eine pro Kind.
  </p>
 </div>

 <div class="simplesect" id="persistent-connections.drawbacks.conn-limits">
  <h3 class="title">Mögliche Nachteile: Verbindungslimits</h3>
  <p class="simpara">
   Es ist jedoch zu beachten, dass dies Nachteile haben kann, wenn eine
   Datenbank mit Verbindungslimits verwendet wird, die durch persistente
   Verbindungen der Kindprozesse überschritten werden. Hat die Datenbank
   ein Limit von 16 gleichzeitigen Verbindungen und versuchen während
   einer stark ausgelasteten Server-Sitzung 17 Kindprozesse, eine
   Verbindung herzustellen, wird einer von ihnen fehlschlagen. Bestehen in
   den Skripten Fehler, die das Schließen der Verbindungen verhindern
   (wie etwa Endlosschleifen), können die verfügbaren 16 Verbindungen schnell
   aufgebraucht sein.
  </p>
  <p class="simpara">
   Persistente Verbindungen erhöhen in der Regel die Anzahl der zu einem
   gegebenen Zeitpunkt geöffneten Verbindungen, da untätige Worker
   weiterhin die Verbindungen halten, die sie für vorherige Anfragen
   geöffnet haben. Werden viele Worker hochgefahren, um eine
   Lastspitze zu bewältigen, bleiben die von ihnen geöffneten Verbindungen
   bestehen, bis der Worker beendet wird oder der Datenbankserver die
   Verbindung schließt.
  </p>
  <p class="simpara">
   Es ist sicherzustellen, dass die vom Datenbankserver erlaubte maximale
   Anzahl an Verbindungen größer ist als die maximale Anzahl der Worker
   für Web-Anfragen (zuzüglich aller weiteren Verwendungen wie Cronjobs
   oder administrativer Verbindungen).
  </p>
  <p class="simpara">
   Es empfiehlt sich, in der Dokumentation der Datenbank nachzuschlagen, wie
   der Datenbankserver aufgegebene oder im Leerlauf befindliche Verbindungen
   per Timeout behandelt. Lange Timeouts können die Anzahl der zu einem
   Zeitpunkt geöffneten persistenten Verbindungen erheblich erhöhen.
  </p>
 </div>

 <div class="simplesect" id="persistent-connections.drawbacks.state">
  <h3 class="title">Mögliche Nachteile: Verwaltung des Verbindungszustands</h3>
  <p class="simpara">
   Manche Datenbank-Erweiterungen führen eine automatische Bereinigung
   durch, wenn die Verbindung wiederverwendet wird; andere überlassen
   diese Aufgabe dem Anwendungsentwickler. Je nach gewählter
   Datenbank-Erweiterung und Anwendungsdesign kann eine manuelle Bereinigung
   vor Beendigung des Skripts erforderlich sein. Änderungen, die
   Verbindungen in einem unerwarteten Zustand zurücklassen können, sind
   unter anderem:
  </p>
  <ul class="simplelist">
   <li>Ausgewählte/voreingestellte Datenbank</li>
   <li>Tabellensperren</li>
   <li>Nicht abgeschlossene Transaktionen</li>
   <li>Temporäre Tabellen</li>
   <li>Verbindungsspezifische Einstellungen oder Funktionen wie Profiling</li>
  </ul>
  <p class="simpara">
   Tabellensperren und Transaktionen, die nicht aufgeräumt oder
   abgeschlossen werden, können dazu führen, dass andere Abfragen
   unbegrenzt blockiert werden und/oder dass eine spätere
   Wiederverwendung der Verbindung unerwartete Änderungen verursacht.
  </p>
  <p class="simpara">
   Ist die falsche Datenbank ausgewählt, kann eine spätere
   Wiederverwendung der Verbindung Abfragen nicht wie erwartet ausführen
   (oder führt sie auf der falschen Datenbank aus, wenn sich die Schemata
   ausreichend ähneln).
  </p>
  <p class="simpara">
   Werden temporäre Tabellen nicht aufgeräumt, können nachfolgende
   Anfragen dieselbe Tabelle nicht erneut anlegen.
  </p>
  <p class="simpara">
   Die Bereinigung kann mithilfe von Klassen-Destruktoren oder
   <span class="function"><a href="function.register-shutdown-function.php" class="function">register_shutdown_function()</a></span> umgesetzt werden.
   Dedizierte Connection-Pooling-Proxies, die dies als Teil ihrer
   Funktionalität enthalten, können ebenfalls in Betracht gezogen werden.
  </p>
 </div>

 <div class="simplesect" id="persistent-connections.final-words">
  <h3 class="title">Schlussbemerkungen</h3>
  <p class="simpara">
   Aufgrund des oben beschriebenen Verhaltens und der potenziellen
   Nachteile sollten persistente Verbindungen nicht ohne sorgfältige
   Abwägung eingesetzt werden. Sie sollten nicht ohne zusätzliche
   Anpassungen der Anwendung sowie ohne sorgfältige Konfiguration von
   Datenbankserver und Webserver und/oder PHP-FPM verwendet werden.
  </p>
  <p class="simpara">
   Es sollten alternative Lösungen in Betracht gezogen werden, etwa die
   Untersuchung und Behebung der Ursachen für den
   Verbindungsaufbau-Overhead (beispielsweise das Deaktivieren von
   Reverse-DNS-Lookups auf dem Datenbankserver) oder dedizierte
   Connection-Pooling-Proxies.
  </p>
  <p class="simpara">
   Für Web-APIs mit hohem Anfragevolumen sollten alternative Runtimes oder
   langlaufende Anwendungsserver in Betracht gezogen werden.
  </p>
 </div>

 <div class="simplesect" id="persistent-connections.seealso">
  <h3 class="title">Siehe auch</h3>
  <ul class="simplelist">
   <li><span class="function"><a href="function.ibase-pconnect.php" class="function">ibase_pconnect()</a></span></li>
   <li><span class="function"><a href="function.oci-pconnect.php" class="function">oci_pconnect()</a></span></li>
   <li><span class="function"><a href="function.odbc-pconnect.php" class="function">odbc_pconnect()</a></span></li>
   <li><span class="function"><a href="function.pfsockopen.php" class="function">pfsockopen()</a></span></li>
   <li><span class="function"><a href="function.pg-connect.php" class="function">pg_connect()</a></span></li>
   <li><a href="mysqli.persistconns.php" class="link">MySQLi und persistente Verbindungen</a></li>
   <li><a href="pdo.connections.php" class="link">PDO-Verbindungsverwaltung</a></li>
  </ul>
 </div>
</div>
<?php manual_footer($setup); ?>