<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/book.mysqlnd.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'de',
  ),
  'this' => 
  array (
    0 => 'mysqlnd.memory.php',
    1 => 'Speicherverwaltung',
    2 => 'Speicherverwaltung',
  ),
  'up' => 
  array (
    0 => 'book.mysqlnd.php',
    1 => 'Mysqlnd',
  ),
  'prev' => 
  array (
    0 => 'mysqlnd.notes.php',
    1 => 'Hinweise',
  ),
  'next' => 
  array (
    0 => 'mysqlnd.plugin.php',
    1 => 'Plugin-API des MySQL Native Drivers',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'de',
    'path' => 'reference/mysqlnd/memory.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="mysqlnd.memory" class="chapter">
 <h1 class="title">Speicherverwaltung</h1>

 <p class="simpara">
  <strong>Einführung</strong>
 </p>
 <p class="simpara">
  Der MySQL Native Driver verwaltet den Speicher anders als die MySQL Client
  Library. Die Bibliotheken unterscheiden sich in der Art und Weise, wie
  Speicher zugewiesen und freigegeben wird, wie Speicher beim Lesen von
  MySQL-Ergebnissen in Teilstücken zugewiesen wird, welche Debug- und
  Entwicklungsoptionen existieren und wie von MySQL gelesene Ergebnisse mit
  PHP-Benutzervariablen verknüpft werden.
 </p>
 <p class="simpara">
  Die folgenden Hinweise sind als Einführung und Zusammenfassung für Benutzer
  gedacht, die daran interessiert sind, den MySQL Native Driver auf
  C-Code-Ebene zu verstehen.
 </p>
 <p class="simpara">
  <strong>Für die Speicherverwaltung verwendete Funktionen</strong>
 </p>
 <p class="simpara">
  Alle Zuweisungen und Freigaben von Speicher erfolgen über die Funktionen der
  PHP-Speicherverwaltung, weshalb der Speicherverbrauch von mysqlnd mit Hilfe
  von PHP-API-Aufrufen wie <span class="function"><a href="function.memory-get-usage.php" class="function">memory_get_usage()</a></span> verfolgt
  werden kann. Da der Speicher über die PHP-Speicherverwaltung zugewiesen und
  freigegeben wird, werden die Änderungen möglicherweise nicht sofort auf der
  Ebene des Betriebssystems sichtbar. Die PHP-Speicherverwaltung fungiert als
  Proxy, der die Freigabe von Speicher an das System eventuell verzögert. Aus
  diesem Grund ist ein Vergleich des Speicherverbrauchs des MySQL Native
  Drivers und der MySQL Client Library schwierig. Die MySQL Client Library
  verwendet direkt die Aufrufe der Speicherverwaltung des Betriebssystems,
  sodass die Auswirkungen sofort auf der Betriebssystemebene beobachtet werden
  können.
 </p>
 <p class="simpara">
  Jede von PHP erzwungene Speicherbegrenzung wirkt sich auch auf den MySQL
  Native Driver aus. Dies kann zu &quot;Out-of-Memory&quot;-Fehlern führen, wenn große
  Ergebnismengen abgerufen werden, die die Größe des von PHP zur Verfügung
  gestellten Speichers überschreiten. Da die MySQL Client Library nicht die
  Funktionen der PHP-Speicherverwaltung verwendet, unterliegt sie nicht den
  von PHP gesetzten Speichergrenzen. Wenn die MySQL Client Library verwendet
  wird, kann der Speicherbedarf eines PHP-Prozesses je nach Einsatzmodell über
  das PHP-Speicherlimit hinaus anwachsen. Gleichzeitig sind PHP-Skripte in der
  Lage, größere Ergebnismengen zu verarbeiten, da der für die Speicherung der
  Ergebnismengen vorgesehene Speicher nicht unter der Kontrolle von PHP steht.
 </p>
 <p class="simpara">
  Die Funktionen der PHP-Speicherverwaltung werden vom MySQL Native Driver
  über einen schlanken Wrapper aufgerufen. Der Wrapper erleichtert unter
  anderem das Debugging.
 </p>
 <p class="simpara">
  <strong>Handhabung von Ergebnismengen</strong>
 </p>
 <p class="simpara">
  Die verschiedenen MySQL-Server- und Client-APIs unterscheiden zwischen
  <a href="mysqli.quickstart.statements.php" class="link">gepufferten und ungepufferten</a>
  Ergebnismengen. Ungepufferte Ergebnismengen werden Zeile für Zeile von MySQL
  zum Client übertragen, während der Client die Ergebnisse durchläuft.
  Gepufferte Ergebnisse werden in ihrer Gesamtheit von der Client-Bibliothek
  abgerufen, bevor sie an den Client weitergegeben werden.
 </p>
 <p class="simpara">
  Der MySQL Native Driver verwendet PHP-Streams für die Kommunikation mit dem
  MySQL-Server. Die von MySQL gesendeten Ergebnisse werden aus den
  Netzwerkpuffern der PHP-Streams in den Ergebnispuffer von mysqlnd abgerufen.
  Der Ergebnispuffer besteht aus Zvals. In einem zweiten Schritt werden die
  Ergebnisse dem PHP-Skript zur Verfügung gestellt. Diese abschließende
  Übertragung vom Ergebnispuffer in PHP-Variablen wirkt sich auf den
  Speicherverbrauch aus und macht sich vor allem dann bemerkbar, wenn
  gepufferte Ergebnismengen verwendet werden.
 </p>
 <p class="simpara">
  Standardmäßig versucht der MySQL Native Driver zu vermeiden, dass gepufferte
  Ergebnisse doppelt im Speicher gehalten werden. Die Ergebnisse werden nur
  einmal im internen Ergebnispuffer und ihren Zvals gespeichert. Wenn die
  Ergebnisse vom PHP-Skript in PHP-Variablen abgerufen werden, verweisen die
  Variablen auf den internen Ergebnispuffer. Ergebnisse von Datenbankabfragen
  werden nicht kopiert und nur einmal im Speicher gehalten. Wenn ein Benutzer
  den Inhalt einer Variable ändert, die Ergebnisse einer Datenbankabfrage
  enthält, muss ein Copy-on-Write (Kopieren beim Schreiben) durchgeführt
  werden, um zu vermeiden, dass der referenzierte interne Ergebnispuffer
  geändert wird. Der Inhalt des Puffers darf nicht verändert werden, weil der
  Benutzer die Ergebnismenge möglicherweise ein zweites Mal lesen möchte. Der
  Copy-on-Write-Mechanismus wird durch eine zusätzliche Liste zur Verwaltung
  der Referenzen und die Verwendung von Standard-Zval-Referenzzählern
  realisiert. Copy-on-Write muss auch dann durchgeführt werden, wenn der
  Benutzer eine Ergebnismenge in PHP-Variablen einliest und eine Ergebnismenge
  wieder freigibt, bevor die Variablen zurückgesetzt werden.
 </p>
 <p class="simpara">
  Im Allgemeinen funktioniert diese Vorgehensweise gut bei Skripten, die eine
  Ergebnismenge einmal lesen und die Variablen mit den Ergebnissen nicht
  verändern. Ihr größter Nachteil ist der durch die zusätzliche
  Referenzverwaltung verursachte zusätzliche Speicherbedarf. Dieser rührt in
  erster Linie daher, dass Benutzervariablen, die Ergebnisse enthalten, erst
  dann vollständig freigegeben werden können, wenn sie nicht mehr von der
  mysqlnd-Referenzverwaltung referenziert werden. Der MySQL Native Driver
  entfernt die Referenz auf die Benutzervariablen, wenn die Ergebnismenge
  freigegeben wird oder wenn ein Copy-on-Write durchgeführt wird. Ein
  Beobachter sieht, wie der Gesamtspeicherbedarf solange ansteigt, bis die
  Ergebnismenge freigegeben wird. Mit Hilfe der
  <a href="mysqlnd.stats.php" class="link">Statistiken</a> kann überprüft werden, ob
  ein Skript die Ergebnismenge explizit freigibt oder ob sie vom Treiber
  implizit freigegeben wird und somit der Speicher länger als nötig verwendet
  wird. Anhand der Statistiken lässt sich auch feststellen, wie viele
  Copy-on-Write-Operationen durchgeführt wurden.
 </p>
 <p class="simpara">
  Ein PHP-Skript, das viele kleine Zeilen aus einer gepufferten Ergebnismenge
  ausliest und dazu einen Codeschnipsel verwendet, der <code class="literal">while ($row =
  $res-&gt;fetch_assoc()) { ... }</code> entspricht, kann den
  Speicherbedarf optimieren, indem es Kopien anstelle von Referenzen
  anfordert. Kopien anzufordern bedeutet zwar, dass die Ergebnisse doppelt im
  Speicher gehalten werden, aber es erlaubt PHP, die in
  <code class="literal">$row</code> enthaltene Kopie schon freizugeben, während die
  Ergebnismenge durchlaufen wird, statt erst, wenn die Ergebnismenge selbst
  freigegeben wird. Auf einem stark ausgelasteten Server kann die Optimierung
  der Spitzenspeichernutzung dazu beitragen, die Gesamtleistung des Systems zu
  verbessern, obwohl der Weg über Kopien für ein einzelnes Skript aufgrund
  zusätzlicher Zuweisungen und Speicherkopiervorgänge langsamer sein kann.
 </p>
 <p class="simpara">
  <strong>Überwachung und Fehlersuche</strong>
 </p>
 <p class="simpara">
  Es gibt mehrere Möglichkeiten, die Speichernutzung des MySQL Native Drivers
  zu verfolgen. Um einen schnellen Überblick zu erhalten oder die
  Speichereffizienz von PHP-Skripten zu überprüfen, empfiehlt sich ein Blick
  auf die <a href="mysqlnd.stats.php" class="link">Statistiken</a>, die von der
  Bibliothek gesammelt werden. Anhand der Statistiken können z. B.
  SQL-Anweisungen erkannt werden, die mehr Ergebnisse erzeugen als von einem
  PHP-Skript verarbeitet werden.
 </p>
 <p class="simpara">
  Das <a href="mysqlnd.config.php#ini.mysqlnd.debug" class="link">Debug</a>-Trace-Protokoll kann so
  konfiguriert werden, dass es Aufrufe der Speicherverwaltung aufzeichnet. Das
  ist hilfreich, um zu sehen, wann Speicher zugewiesen oder freigegeben wird.
  Die Größe der angeforderten Speicherabschnitte wird jedoch möglicherweise
  nicht aufgeführt.
 </p>
 <p class="simpara">
  Einige neuere Versionen des MySQL Native Drivers bieten die Emulation von
  zufälligen &quot;Out-of-Memory&quot;-Situationen. Diese Funktion ist nur für die
  C-Entwickler der Bibliothek oder die Autoren des
  mysqlnd-<a href="mysqlnd.plugin.php" class="link">Plugins</a> gedacht. Die
  entsprechenden PHP-Konfigurationseinstellungen und weitere Details sind im
  Quellcode zu finden. Die Funktion wird als nicht für die Allgemeinheit
  bestimmt betrachtet und kann jederzeit ohne vorherige Ankündigung geändert
  werden.
 </p>

</div>
<?php manual_footer($setup); ?>