-
Notifications
You must be signed in to change notification settings - Fork 51
Expand file tree
/
Copy pathmemory.xml
More file actions
178 lines (177 loc) · 9.2 KB
/
Copy pathmemory.xml
File metadata and controls
178 lines (177 loc) · 9.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 9598935f21bc472f22383fb989625f0b22785331 Maintainer: samesch Status: ready -->
<!-- Reviewed: no -->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="mysqlnd.memory">
<title>Speicherverwaltung</title>
<simpara>
<emphasis role="bold">Einführung</emphasis>
</simpara>
<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.
</simpara>
<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.
</simpara>
<simpara>
<emphasis role="bold">Für die Speicherverwaltung verwendete Funktionen</emphasis>
</simpara>
<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 <function>memory_get_usage</function> 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.
</simpara>
<simpara>
Jede von PHP erzwungene Speicherbegrenzung wirkt sich auch auf den MySQL
Native Driver aus. Dies kann zu "Out-of-Memory"-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.
</simpara>
<simpara>
Die Funktionen der PHP-Speicherverwaltung werden vom MySQL Native Driver
über einen schlanken Wrapper aufgerufen. Der Wrapper erleichtert unter
anderem das Debugging.
</simpara>
<simpara>
<emphasis role="bold">Handhabung von Ergebnismengen</emphasis>
</simpara>
<simpara>
Die verschiedenen MySQL-Server- und Client-APIs unterscheiden zwischen
<link linkend="mysqli.quickstart.statements">gepufferten und ungepufferten</link>
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.
</simpara>
<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.
</simpara>
<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.
</simpara>
<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
<link linkend="mysqlnd.stats">Statistiken</link> 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.
</simpara>
<simpara>
Ein PHP-Skript, das viele kleine Zeilen aus einer gepufferten Ergebnismenge
ausliest und dazu einen Codeschnipsel verwendet, der <literal>while ($row =
$res->fetch_assoc()) { ... }</literal> 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
<literal>$row</literal> 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.
</simpara>
<simpara>
<emphasis role="bold">Überwachung und Fehlersuche</emphasis>
</simpara>
<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 <link linkend="mysqlnd.stats">Statistiken</link>, die von der
Bibliothek gesammelt werden. Anhand der Statistiken können &zb;
SQL-Anweisungen erkannt werden, die mehr Ergebnisse erzeugen als von einem
PHP-Skript verarbeitet werden.
</simpara>
<simpara>
Das <link linkend="ini.mysqlnd.debug">Debug</link>-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.
</simpara>
<simpara>
Einige neuere Versionen des MySQL Native Drivers bieten die Emulation von
zufälligen "Out-of-Memory"-Situationen. Diese Funktion ist nur für die
C-Entwickler der Bibliothek oder die Autoren des
mysqlnd-<link linkend="mysqlnd.plugin">Plugins</link> 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.
</simpara>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->