mirror of
https://github.com/php/doc-ru.git
synced 2026-04-25 08:18:16 +02:00
160 lines
14 KiB
XML
160 lines
14 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- EN-Revision: e016fe67d1f58dc26592e50a244584fcfcf2604d Maintainer: rjhdby Status: ready -->
|
|
<!-- Reviewed: no -->
|
|
<chapter xml:id="mysqlnd.memory" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<title>Управление памятью</title>
|
|
<para>
|
|
<emphasis role="bold">Введение</emphasis>
|
|
</para>
|
|
<para>
|
|
Встроенный драйвер MySQL (mysqlnd) управляет памятью по-другому,
|
|
в отличие от клиентской библиотеки MySQL (libmysql).
|
|
Библиотеки различаются способом выделения и освобождения памяти, тем, как
|
|
память выделяется по кускам во время чтения результатов из MySQL, существующими опциями
|
|
для отладки и разработки, и тем, как результаты, считанные из MySQL, связаны с
|
|
пользовательскими переменными PHP.
|
|
</para>
|
|
<para>
|
|
Следующая информация предназначена в качестве введения и обобщения для пользователей,
|
|
заинтересованных в понимании <literal>mysqlnd</literal> на уровне C-кода.
|
|
</para>
|
|
<para>
|
|
<emphasis role="bold">Используемые функции для управления памятью</emphasis>
|
|
</para>
|
|
<para>
|
|
Все операции выделения и освобождения памяти происходят используя PHP-функции,
|
|
предназначенные для управления памятью. Поэтому, потребление памяти встроенного
|
|
драйвера MySQL может быть отслежено при помощи вызовов
|
|
PHP API, таких как <function>memory_get_usage</function>. Из-за того, что
|
|
память выделяется и освобождается при помощи системы управления памятью PHP,
|
|
изменения на уровне операционной системы могут быть видны не мгновенно.
|
|
Система управления памятью PHP ведёт себя как прокси, которая может вызывать задержку
|
|
в освобождении памяти. Ввиду этого, сравнение использования памяти встроенного
|
|
драйвера MySQL и клиентской библиотеки
|
|
MySQL (libmysql) довольно сложно. Клиентская библиотека
|
|
MySQL (libmysql) использует систему управления памятью операционной
|
|
системы напрямую, следовательно, эффект на уровне операционной системы может быть виден
|
|
незамедлительно.
|
|
</para>
|
|
<para>
|
|
Любое ограничение памяти, установленное в PHP, также влияет на встроенный драйвер MySQL.
|
|
Это может вызвать ошибки переполнения памяти при извлечении
|
|
больших массивов данных, которые превышают размер оставшейся памяти, предоставленных РНР.
|
|
Из-за того, что клиентская библиотека MySQL не использует
|
|
функций управления памяти PHP, она не подчиняется ограничению памяти, установленному в PHP.
|
|
При использовании libmysql, в зависимости от модели развёртывания, объем
|
|
памяти, занимаемый PHP-процессом, может вырасти за пределы ограничений, установленных в
|
|
PHP. В тоже время, PHP-скрипты могут обрабатывать больший объем массивов данных, так как
|
|
области памяти, выделенные для хранения данных, не находятся под управлением РНР.
|
|
</para>
|
|
<para>
|
|
Функции системы управления памятью PHP вызываются встроенным драйвером MySQL
|
|
через легковесную обёртку. Среди прочего, обёртка
|
|
делает отладку легче.
|
|
</para>
|
|
<para>
|
|
<emphasis role="bold">Обработка массивов полученных данных</emphasis>
|
|
</para>
|
|
<para>
|
|
Различные MySQL-сервера и различные клиентские API различают
|
|
<link linkend="mysqli.quickstart.statements">буферизированные и небуферизированные</link>
|
|
результаты. Небуферизированные результаты передаются строка за строкой от MySQL к клиенту
|
|
и клиент читает их по порядку. Буферизированные результаты забираются клиентской библиотекой
|
|
целиком до передачи их клиенту.
|
|
</para>
|
|
<para>
|
|
Встроенный драйвер MySQL использует PHP-потоки для сетевого
|
|
общения с сервером MySQL. Результаты, посланные MySQL-сервером, выбираются из сетевых
|
|
буферов PHP-потоков в результирующий буфер mysqlnd. Результирующий буфер
|
|
состоит из zvals. На втором шаге результаты становятся доступными
|
|
PHP-скрипту. Последняя передача из результирующего буфера в PHP-переменные вызывает
|
|
потребление памяти и в большинстве случаев оно заметно при использовании буферизированных
|
|
результатов.
|
|
</para>
|
|
<para>
|
|
По умолчанию встроенный драйвер MySQL пытается избежать
|
|
двойного хранения буферного результата в памяти. Результаты хранятся только один раз во
|
|
внутренних результирующих буферах и их zvals. Когда результаты
|
|
забираются в РНР-переменные PHP-скриптом, переменные будут ссылаться на внутренние
|
|
результаты буферов. Результаты запросов к базам данных не копируются и хранятся в памяти
|
|
только один раз. Достаточно пользователю изменить содержимое переменной, содержащей
|
|
результаты работы базы данных, как будет выполнен механизм копирования при записи
|
|
(Copy-On-Write), для того, чтобы избежать изменения ссылающего внутреннего буфера результата.
|
|
Содержимое буфера не должно быть изменено, так как пользователь может принять решение
|
|
прочитать результат во второй раз. Механизм копирования при записи реализуется с помощью
|
|
дополнительного управления списком ссылок и использования стандартных zval счётчиков ссылок.
|
|
Копирование при записи также должно быть сделано, если пользователь читает данные
|
|
результата в PHP переменных и освобождает данные результата прежде, чем переменные будут
|
|
уничтожены.
|
|
</para>
|
|
<para>
|
|
В общем, этот шаблон работает хорошо для скриптов, которые читают наборы данных единожды и
|
|
не изменяют переменных, содержащих результаты. Его главный недостаток в накладных расходах
|
|
памяти, вызванных дополнительным управлением ссылками, причина которого в первую очередь
|
|
связана с тем, что пользовательские переменные, удерживающие результаты, не могут быть
|
|
полностью освобождены до того, как система управления ссылками mysqlnd
|
|
содержит ссылки на них. Встроенный драйвер MySQL удаляет ссылку на
|
|
на пользовательские переменные когда массив полученных данных освобождается или выполняется
|
|
механизм копирования при записи. Наблюдатель увидит рост общего потребления памяти пока
|
|
массив полученных данных не освободится. Используйте <link linkend="mysqlnd.stats">статистику</link>,
|
|
чтобы проверить, скрипт явно произвёл освобождение данных результата или же драйвер сделал
|
|
это неявно и поэтому память используется в течение более долгого времени, чем это необходимо.
|
|
Статистика также помогает увидеть количество операций копирования при записи.
|
|
</para>
|
|
<para>
|
|
PHP-скрипт, читающий множество небольших строк в буферизированном массиве данных, использующий
|
|
код, подобный <literal>while ($row = $res->fetch_assoc()) { ... }</literal>, может
|
|
оптимизировать потребление памяти, запросив копии вместо ссылок. Хотя и запрос копий означает
|
|
хранение тех же результатов в памяти дважды, это позволяет PHP уничтожить копию, содержащую
|
|
в <literal>$row</literal> в качестве итерируемого массива данных и перед уничтожением результат
|
|
устанавливает сам себя. На загруженном сервере оптимизация использования памяти может помочь
|
|
улучшить общую производительность системы, хотя для отдельного скрипта подход с копией вместо
|
|
ссылок может быть медленнее в связи с дополнительным выделением памяти и дополнительными
|
|
операциями копирования в памяти.
|
|
</para>
|
|
<para>
|
|
<emphasis role="bold">Контроль и отладка</emphasis>
|
|
</para>
|
|
<para>
|
|
Существует несколько методов отслеживания использования памяти во встроенном драйвере
|
|
MySQL "mysqlnd". Если цель - получить быстрый высокоуровневый обзор
|
|
или проверить эффективность PHP-скриптов при работе с памятью, то проверьте
|
|
<link linkend="mysqlnd.stats">статистику</link>, собранную библиотекой. Статистика позволит
|
|
вам, например, поймать SQL-запрос, который генерирует больше результатов, чем обрабатываются
|
|
PHP-скриптом.
|
|
</para>
|
|
<para>
|
|
<link linkend="ini.mysqlnd.debug">Журнал отладки</link> может быть сконфигурирован
|
|
для записи вызовов системы управления памятью. Это помогает увидеть когда память
|
|
выделяется и освобождается. Однако, размер запрошенных кусков памяти может не быть в списке.
|
|
</para>
|
|
<para>
|
|
В некоторых последних версиях встроенного драйвера MySQL "mysqlnd"
|
|
присутствует возможность эмуляции случайных ситуаций нехватки памяти. Эта возможность
|
|
была задумана для использования только C-разработчиками библиотеки или авторами
|
|
<link linkend="mysqlnd.plugin">плагина</link> mysqlnd. Пожалуйста, используйте поиск по исходному коду
|
|
для соответствующей настройки PHP и для дальнейшей информации. Это возможность является
|
|
недокументированной и может быть изменена в любое время без дополнительного уведомления.
|
|
</para>
|
|
|
|
</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
|
|
-->
|