mirror of
https://github.com/php/doc-ru.git
synced 2026-03-23 23:32:16 +01:00
243 lines
18 KiB
XML
243 lines
18 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: cd8b964b8566801265f0d287db6eb651f93be950 Maintainer: shein Status: ready -->
|
||
<!-- Reviewed: no -->
|
||
<chapter xml:id="features.persistent-connections" xmlns="http://docbook.org/ns/docbook">
|
||
<title>Постоянные соединения с базами данных</title>
|
||
|
||
<simplesect>
|
||
<title>Что такое постоянные соединения?</title>
|
||
<simpara>
|
||
Постоянные соединения представляют собой связи с базами данных,
|
||
которые не закрываются при завершении скрипта. При получении запроса
|
||
на постоянное соединение PHP вначале проверяет, имеется ли
|
||
идентичное постоянное соединение (которое было открыто при предыдущих
|
||
обращениях) и, если таковое было найдено, использует его.
|
||
В случае если идентичного соединения нет, PHP создаёт новое. Под
|
||
"идентичным" подразумевается соединение, открытое на том же хосте с
|
||
таким же именем пользователя и паролем (если они указаны).
|
||
</simpara>
|
||
<simpara>
|
||
Нет способа запросить конкретное соединение или гарантировать,
|
||
что вы получите существующее соединение или совершенно новое
|
||
(если все существующие соединения заняты или запрос обслуживается другим процессом,
|
||
у которого есть отдельный пул соединений).
|
||
</simpara>
|
||
<simpara>
|
||
Это значит, что вы не можете использовать постоянные соединения PHP, например, для:
|
||
</simpara>
|
||
<simplelist>
|
||
<member>назначения определённой сессии базы данных конкретному веб-пользователю</member>
|
||
<member>создания крупной транзакции, охватывающей несколько запросов</member>
|
||
<member>инициализации запроса для одного запроса и собирания результатов по другому</member>
|
||
</simplelist>
|
||
<simpara>
|
||
Постоянные соединения не предоставляют вам <emphasis>никаких</emphasis> функций,
|
||
которые были бы недоступны при использовании непостоянных соединений.
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.web">
|
||
<title>Веб-запросы</title>
|
||
<simpara>
|
||
Существует два основных способа использования PHP сервером для генерации
|
||
веб-страниц.
|
||
</simpara>
|
||
<simpara>
|
||
Первый способ заключается в том, чтобы использовать PHP как CGI-обёртку.
|
||
При этом PHP-интерпретатор создаётся и уничтожается при каждом
|
||
обращении к странице (PHP-скрипту). Поскольку интерпретатор
|
||
уничтожается после каждого запроса к серверу, все используемые им ресурсы
|
||
(в том числе и соединение с базой данных) закрываются. Следовательно,
|
||
в этом случае вы не получите ничего от использования постоянных соединений -
|
||
их просто нет.
|
||
</simpara>
|
||
<simpara>
|
||
Второй и наиболее популярный метод заключается в запуске PHP-FPM или PHP
|
||
в качестве модуля в многопроцессорном веб-сервере, которым в настоящее время
|
||
является только Apache.
|
||
В таких конфигурациях обычно можно выделить один процесс
|
||
(родительский), который координирует работу всех остальных процессов
|
||
(дочерних), которые фактически и выполняют работу по обслуживанию веб-страниц.
|
||
При каждом обращении клиента к серверу запрос перенаправляется одному из
|
||
дочерних процессов, который в данный момент не занят обслуживанием другого
|
||
клиента. Это означает, что когда тот же самый клиент выполняет повторный
|
||
запрос к серверу, он может быть обработан другим дочерним процессом, отличным
|
||
от того, который был при первом обращении. После открытия постоянного
|
||
соединения каждая последующая страница, требующая соединения с базой данных,
|
||
может использовать уже установленное ранее соединение с SQL-сервером.
|
||
</simpara>
|
||
<note>
|
||
<para>
|
||
Вы можете проверить, какой метод используют ваши веб-запросы,
|
||
проверив значение «Server API» в выводе функции <function>phpinfo</function>
|
||
или значение константы <constant>PHP_SAPI</constant>,
|
||
полученное из веб-запроса.
|
||
</para>
|
||
<para>
|
||
Если API сервера является «Apache 2 Handler» или «FPM/FastCGI»,
|
||
то постоянные соединения будут использоваться для всех запросов,
|
||
обслуживаемых одним и тем же рабочим процессом.
|
||
Для любого другого значения постоянные соединения не будут сохраняться
|
||
после каждого запроса.
|
||
</para>
|
||
</note>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.cli">
|
||
<title>Процессы командной строки</title>
|
||
<simpara>
|
||
Поскольку PHP в командной строке использует новый процесс для каждого скрипта,
|
||
постоянные соединения не используются совместно между скриптами командной строки,
|
||
поэтому нет смысла использовать их во временных скриптах, таких как задания Cron или команды.
|
||
Однако они могут быть полезны, если, например, вы пишете долго работающий сервер приложений,
|
||
который обслуживает много запросов или задач, и каждому из них может потребоваться
|
||
собственное соединение с базой данных.
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.why">
|
||
<title>Зачем их использовать?</title>
|
||
<simpara>
|
||
Постоянные соединения полезны в том случае, если при открытии большого количества SQL-соединений
|
||
возникает ощутимая нагрузка на сервер. То, насколько велика эта нагрузка,
|
||
зависит от многих факторов. Например, от того, какая именно база данных
|
||
используется, находится ли она на том же компьютере что и ваш веб-сервер,
|
||
насколько загружена машина, на которой установлен SQL-сервер, и так далее.
|
||
В случае, если затраты на установку соединения велики, постоянные соединения
|
||
могут вам существенно помочь. Они позволяют дочернему процессу на
|
||
протяжении всего жизненного цикла использовать одно и то же соединение
|
||
вместо того, чтобы создавать его при обработке каждой страницы,
|
||
которая взаимодействует с SQL-сервером. Это означает, что каждый дочерний
|
||
процесс, открывший постоянное соединение, будет иметь своё собственное
|
||
соединение с сервером. Например, если у вас запущено 20 дочерних процессов,
|
||
которые выполнили скрипт, использовавший постоянное соединение с SQL-сервером,
|
||
вы получите 20 различных соединений с SQL-сервером, по одному на каждый дочерний
|
||
процесс.
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.drawbacks.conn-limits">
|
||
<title>Возможные недостатки: ограничения подключения</title>
|
||
<simpara>
|
||
Следует заметить, что этот подход имеет некоторые недостатки: если
|
||
вы используете базу данных с ограниченным количеством возможных
|
||
подключений, оно может быть превышено количеством запрашиваемых
|
||
дочерними процессами постоянных соединений. Например, если ваша база
|
||
данных позволяет 16 одновременных соединений, и во время нагрузки
|
||
на сервер 17 дочерних процессов попробуют открыть соединение, одна из
|
||
попыток потерпит неудачу. Если в вашем коде содержатся ошибки, не позволяющие
|
||
закрывать соединение (например, бесконечные циклы), база данных с
|
||
16 одновременными подключениями вскоре может оказаться заблокированной.
|
||
</simpara>
|
||
<simpara>
|
||
Постоянные соединения обычно увеличивают количество соединений,
|
||
открытых в любой момент времени, поскольку неактивные рабочие процессы по-прежнему
|
||
удерживают соединения для предыдущих запросов, которые они обслуживали.
|
||
Если для обработки потока запросов запускается большое количество рабочих процессов,
|
||
открытые ими соединения остаются открытыми до тех пор,
|
||
пока рабочий процесс не будет завершён или сервер базы данных не закроет соединение.
|
||
</simpara>
|
||
<simpara>
|
||
Убедитесь, что максимальное количество подключений, разрешённое сервером базы данных,
|
||
превышает максимальное количество рабочих процессов веб-запросов (плюс любое другое использование,
|
||
такое как задания Cron или административные подключения).
|
||
</simpara>
|
||
<simpara>
|
||
Проверьте документацию по базе данных для получения информации об обработке заброшенных
|
||
или неактивных соединений (время ожидания). Длительное время ожидания может
|
||
значительно увеличить количество постоянных соединений, открытых в любой момент времени.
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.drawbacks.state">
|
||
<title>Возможные недостатки: поддержание состояния соединения</title>
|
||
<simpara>
|
||
Некоторые модули баз данных выполняют автоматическую очистку
|
||
при повторном использовании соединения; другие оставляют эту задачу
|
||
на усмотрение разработчика приложения.
|
||
В зависимости от выбранного модуля базы данных и конструкции приложения
|
||
перед завершением работы скрипта может потребоваться ручная очистка.
|
||
К изменениям, которые могут привести к неожиданному состоянию соединений,
|
||
относятся:
|
||
</simpara>
|
||
<simplelist>
|
||
<member>Выбранная / базовая база данных</member>
|
||
<member>Блокировка таблиц</member>
|
||
<member>Незавершённые транзакции</member>
|
||
<member>Временные таблицы</member>
|
||
<member>Настройки или функции, специфичные для подключения, такие как профилирование</member>
|
||
</simplelist>
|
||
<simpara>
|
||
Блокировки таблиц и транзакции, которые не очищаются или не закрываются,
|
||
могут привести к бесконечной блокировке других запросов и/или
|
||
к неожиданным изменениям при повторном использовании соединения.
|
||
</simpara>
|
||
<simpara>
|
||
Выбор неправильной базы данных приведёт к тому, что при последующем повторном
|
||
использовании соединения запросы не будут выполняться должным образом
|
||
(или будут выполняться в неправильной базе данных, если схемы достаточно похожи).
|
||
</simpara>
|
||
<simpara>
|
||
Если временные таблицы не очищаются, последующие запросы не смогут воссоздать ту же таблицу.
|
||
</simpara>
|
||
<simpara>
|
||
Вы можете реализовать очистку с помощью деструкторов классов или
|
||
функции <function>register_shutdown_function</function>.
|
||
Вы также можете рассмотреть возможность использования специальных прокси-серверов для пула подключений,
|
||
которые включают функцию в свой набор возможностей.
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect xml:id="persistent-connections.final-words">
|
||
<title>Заключительные слова</title>
|
||
<simpara>
|
||
Учитывая их поведение и потенциальные недостатки, описанные выше,
|
||
не следует использовать постоянные соединения без тщательного обдумывания.
|
||
Их не следует использовать без внедрения дополнительных изменений в ваше приложение
|
||
и тщательной настройки вашего сервера базы данных и веб-сервера и/или PHP-FPM.
|
||
</simpara>
|
||
<simpara>
|
||
Рассмотрите альтернативные решения, такие как исследование и устранение причин накладных расходов
|
||
на создание соединений (например, отключение обратного DNS-поиска на сервере базы данных)
|
||
или использование специальных прокси-серверов для объединения соединений.
|
||
</simpara>
|
||
<simpara>
|
||
Для веб API с большим объёмом данных рассмотрите возможность использования альтернативных сред
|
||
выполнения или серверов приложений с длительным временем работы.
|
||
</simpara>
|
||
</simplesect>
|
||
|
||
<simplesect role="seealso" xml:id="persistent-connections.seealso">
|
||
&reftitle.seealso;
|
||
<simplelist>
|
||
<member><function>ibase_pconnect</function></member>
|
||
<member><function>oci_pconnect</function></member>
|
||
<member><function>odbc_pconnect</function></member>
|
||
<member><function>pfsockopen</function></member>
|
||
<member><function>pg_connect</function></member>
|
||
<member><link linkend="mysqli.persistconns">Модуль MySQLi и постоянные соединения</link></member>
|
||
<member><link linkend="pdo.connections">Подключения и управление подключениями</link></member>
|
||
</simplelist>
|
||
</simplesect>
|
||
</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
|
||
-->
|