/
concepts.xml
190 lines (161 loc) · 6.67 KB
/
concepts.xml
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
179
180
181
182
183
184
185
186
187
188
189
190
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<chapter xml:id="mysqlinfo.concepts" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Concepts</title>
<para>
These concepts are specific to the MySQL drivers for PHP.
</para>
<section xml:id="mysqlinfo.concepts.buffering">
<title>Buffered and Unbuffered queries</title>
<para>
Queries are using the buffered mode by default. This means that query results are
immediately transferred from the MySQL Server to PHP and then are kept in the memory
of the PHP process. This allows additional operations like counting the
number of rows, and moving (seeking) the current result pointer. It also allows
issuing further queries on the same connection while working on the result set.
The downside of the buffered mode is that larger result sets might require
quite a lot memory. The memory will be kept occupied till all references to the
result set are unset or the result set was explicitly freed, which will automatically
happen during request end at the latest. The terminology "store result" is also used
for buffered mode, as the whole result set is stored at once.
</para>
<note>
<para>
When using libmysqlclient as library PHP's memory limit won't count the memory used
for result sets unless the data is fetched into PHP variables. With mysqlnd
the memory accounted for will include the full result set.
</para>
</note>
<para>
Unbuffered MySQL queries execute the query and then wait
for the data from the MySQL server to be fetched. This uses less memory
on the PHP-side, but can increase the load on the server. Unless the full result set was
fetched from the server no further queries can be sent over the same connection. Unbuffered
queries can also be referred to as "use result". Once all rows in the result set
are fetched, the result set is gone and it cannot be iterated again.
</para>
<para>
Following these characteristics, unbuffered queries should be used only
when a large result set is expected that will be processed sequentially.
Unbuffered queries contain a number of pitfalls that makes it more
difficult to use them, e.g. the number of rows in the result set is unknown
until the last row is fetched.
Buffered queries are the easier and more flexible way to process result sets.
</para>
<!-- @TODO
- Add list of issues people run into with unbuffered queries
- Add list of specific use cases for when unbuffered queries are useful
- Question: Unbuffered queries still require all rows to be returned or resource free before executing another? Applies to all extensions?
- Show "free_result" functions / unset usage with buffered queries 8double-check with Andrey on mysqlnd optimizations
-->
<para>
Because buffered queries are the default, the examples below will demonstrate how to
execute unbuffered queries with each API.
</para>
<example>
<title>Unbuffered query example: mysqli</title>
<programlisting role="php">
<![CDATA[
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
$unbufferedResult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT);
foreach ($unbufferedResult as $row) {
echo $row['Name'] . PHP_EOL;
}
?>
]]>
</programlisting>
</example>
<example>
<title>Unbuffered query example: pdo_mysql</title>
<programlisting role="php">
<![CDATA[
<?php
$pdo = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_password');
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$unbufferedResult = $pdo->query("SELECT Name FROM City");
foreach ($unbufferedResult as $row) {
echo $row['Name'] . PHP_EOL;
}
?>
]]>
</programlisting>
</example>
</section>
<section xml:id="mysqlinfo.concepts.charset">
<title>Character sets</title>
<para>
Ideally a proper character set will be set at the server level, and doing this is described
within the <link xlink:href="&url.mysql.charsets.config;">Character Set Configuration</link>
section of the MySQL Server manual. Alternatively, each MySQL API offers a method to set
the character set at runtime.
</para>
<caution>
<title>The character set and character escaping</title>
<para>
The character set should be understood and defined, as it has an affect on every
action, and includes security implications. For example, the escaping mechanism
(e.g., <function>mysqli_real_escape_string</function> for mysqli and <methodname>PDO::quote</methodname> for PDO_MySQL) will adhere to
this setting. It is important to realize that these functions will not use the character
set that is defined with a query, so for example the following will not have an effect
on them:
</para>
</caution>
<example>
<title>Problems with setting the character set with SQL</title>
<programlisting role="php">
<![CDATA[
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
// Will NOT affect $mysqli->real_escape_string();
$mysqli->query("SET NAMES utf8mb4");
// Will NOT affect $mysqli->real_escape_string();
$mysqli->query("SET CHARACTER SET utf8mb4");
// But, this will affect $mysqli->real_escape_string();
$mysqli->set_charset('utf8mb4');
// But, this will NOT affect it (UTF-8 vs utf8mb4) -- don't use dashes here
$mysqli->set_charset('UTF-8');
?>
]]>
</programlisting>
</example>
<para>
Below are examples that demonstrate how to properly alter the character set at runtime
using each API.
</para>
<note>
<title>Possible UTF-8 confusion</title>
<para>
Because character set names in MySQL do not contain dashes, the string
"utf8" is valid in MySQL to set the character set to UTF-8 (up to 3 byte UTF-8 Unicode Encoding). The string
"UTF-8" is not valid, as using "UTF-8" will fail to change the character set and will throw an error.
</para>
</note>
<example>
<title>Setting the character set example: mysqli</title>
<programlisting role="php">
<![CDATA[
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
echo 'Initial character set: ' . $mysqli->character_set_name() . "\n";
if (!$mysqli->set_charset('utf8mb4')) {
printf("Error loading character set utf8mb4: %s\n", $mysqli->error);
exit;
}
echo 'Your current character set is: ' . $mysqli->character_set_name() . "\n";
?>
]]>
</programlisting>
</example>
<example>
<title>Setting the character set example: <link linkend="ref.pdo-mysql.connection">pdo_mysql</link></title>
<programlisting role="php">
<![CDATA[
<?php
$pdo = new PDO("mysql:host=localhost;dbname=world;charset=utf8mb4", 'my_user', 'my_pass');
?>
]]>
</programlisting>
</example>
</section>
</chapter>