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