1
0
mirror of https://github.com/php/doc-ru.git synced 2026-03-23 23:32:16 +01:00
Files
archived-doc-ru/features/persistent-connections.xml
2026-02-06 00:50:28 +03:00

243 lines
18 KiB
XML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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
-->