There's a third case for PHP: run on a fastCGI interface. In this case, PHP processes are NOT destroyed after each request, and so persistent connections do persist. Set PHP_FCGI_CHILDREN << mysql's max_connections and you'll be fine.Постоянные соединения представляют собой связи с базами данных, которые не закрываются при завершении скрипта. При получении запроса на постоянное соединение PHP вначале проверяет, имеется ли идентичное постоянное соединение (которое было открыто при предыдущих обращениях) и, если таковое было найдено, использует его. В случае если идентичного соединения нет, PHP создаёт новое. Под "идентичным" подразумевается соединение, открытое на том же хосте с таким же именем пользователя и паролем (если они указаны).
Нет способа запросить конкретное соединение или гарантировать, что вы получите существующее соединение или совершенно новое (если все существующие соединения заняты или запрос обслуживается другим процессом, у которого есть отдельный пул соединений).
Это значит, что вы не можете использовать постоянные соединения PHP, например, для:
Постоянные соединения не предоставляют вам никаких функций, которые были бы недоступны при использовании непостоянных соединений.
Существует два основных способа использования PHP сервером для генерации веб-страниц.
Первый способ заключается в том, чтобы использовать PHP как CGI-обёртку. При этом PHP-интерпретатор создаётся и уничтожается при каждом обращении к странице (PHP-скрипту). Поскольку интерпретатор уничтожается после каждого запроса к серверу, все используемые им ресурсы (в том числе и соединение с базой данных) закрываются. Следовательно, в этом случае вы не получите ничего от использования постоянных соединений - их просто нет.
Второй и наиболее популярный метод заключается в запуске PHP-FPM или PHP в качестве модуля в многопроцессорном веб-сервере, которым в настоящее время является только Apache. В таких конфигурациях обычно можно выделить один процесс (родительский), который координирует работу всех остальных процессов (дочерних), которые фактически и выполняют работу по обслуживанию веб-страниц. При каждом обращении клиента к серверу запрос перенаправляется одному из дочерних процессов, который в данный момент не занят обслуживанием другого клиента. Это означает, что когда тот же самый клиент выполняет повторный запрос к серверу, он может быть обработан другим дочерним процессом, отличным от того, который был при первом обращении. После открытия постоянного соединения каждая последующая страница, требующая соединения с базой данных, может использовать уже установленное ранее соединение с SQL-сервером.
Замечание:
Вы можете проверить, какой метод используют ваши веб-запросы, проверив значение «Server API» в выводе функции phpinfo() или значение константы
PHP_SAPI, полученное из веб-запроса.Если API сервера является «Apache 2 Handler» или «FPM/FastCGI», то постоянные соединения будут использоваться для всех запросов, обслуживаемых одним и тем же рабочим процессом. Для любого другого значения постоянные соединения не будут сохраняться после каждого запроса.
Поскольку PHP в командной строке использует новый процесс для каждого скрипта, постоянные соединения не используются совместно между скриптами командной строки, поэтому нет смысла использовать их во временных скриптах, таких как задания Cron или команды. Однако они могут быть полезны, если, например, вы пишете долго работающий сервер приложений, который обслуживает много запросов или задач, и каждому из них может потребоваться собственное соединение с базой данных.
Постоянные соединения полезны в том случае, если при открытии большого количества SQL-соединений возникает ощутимая нагрузка на сервер. То, насколько велика эта нагрузка, зависит от многих факторов. Например, от того, какая именно база данных используется, находится ли она на том же компьютере что и ваш веб-сервер, насколько загружена машина, на которой установлен SQL-сервер, и так далее. В случае, если затраты на установку соединения велики, постоянные соединения могут вам существенно помочь. Они позволяют дочернему процессу на протяжении всего жизненного цикла использовать одно и то же соединение вместо того, чтобы создавать его при обработке каждой страницы, которая взаимодействует с SQL-сервером. Это означает, что каждый дочерний процесс, открывший постоянное соединение, будет иметь своё собственное соединение с сервером. Например, если у вас запущено 20 дочерних процессов, которые выполнили скрипт, использовавший постоянное соединение с SQL-сервером, вы получите 20 различных соединений с SQL-сервером, по одному на каждый дочерний процесс.
Следует заметить, что этот подход имеет некоторые недостатки: если вы используете базу данных с ограниченным количеством возможных подключений, оно может быть превышено количеством запрашиваемых дочерними процессами постоянных соединений. Например, если ваша база данных позволяет 16 одновременных соединений, и во время нагрузки на сервер 17 дочерних процессов попробуют открыть соединение, одна из попыток потерпит неудачу. Если в вашем коде содержатся ошибки, не позволяющие закрывать соединение (например, бесконечные циклы), база данных с 16 одновременными подключениями вскоре может оказаться заблокированной.
Постоянные соединения обычно увеличивают количество соединений, открытых в любой момент времени, поскольку неактивные рабочие процессы по-прежнему удерживают соединения для предыдущих запросов, которые они обслуживали. Если для обработки потока запросов запускается большое количество рабочих процессов, открытые ими соединения остаются открытыми до тех пор, пока рабочий процесс не будет завершён или сервер базы данных не закроет соединение.
Убедитесь, что максимальное количество подключений, разрешённое сервером базы данных, превышает максимальное количество рабочих процессов веб-запросов (плюс любое другое использование, такое как задания Cron или административные подключения).
Проверьте документацию по базе данных для получения информации об обработке заброшенных или неактивных соединений (время ожидания). Длительное время ожидания может значительно увеличить количество постоянных соединений, открытых в любой момент времени.
Некоторые модули баз данных выполняют автоматическую очистку при повторном использовании соединения; другие оставляют эту задачу на усмотрение разработчика приложения. В зависимости от выбранного модуля базы данных и конструкции приложения перед завершением работы скрипта может потребоваться ручная очистка. К изменениям, которые могут привести к неожиданному состоянию соединений, относятся:
Блокировки таблиц и транзакции, которые не очищаются или не закрываются, могут привести к бесконечной блокировке других запросов и/или к неожиданным изменениям при повторном использовании соединения.
Выбор неправильной базы данных приведёт к тому, что при последующем повторном использовании соединения запросы не будут выполняться должным образом (или будут выполняться в неправильной базе данных, если схемы достаточно похожи).
Если временные таблицы не очищаются, последующие запросы не смогут воссоздать ту же таблицу.
Вы можете реализовать очистку с помощью деструкторов классов или функции register_shutdown_function(). Вы также можете рассмотреть возможность использования специальных прокси-серверов для пула подключений, которые включают функцию в свой набор возможностей.
Учитывая их поведение и потенциальные недостатки, описанные выше, не следует использовать постоянные соединения без тщательного обдумывания. Их не следует использовать без внедрения дополнительных изменений в ваше приложение и тщательной настройки вашего сервера базы данных и веб-сервера и/или PHP-FPM.
Рассмотрите альтернативные решения, такие как исследование и устранение причин накладных расходов на создание соединений (например, отключение обратного DNS-поиска на сервере базы данных) или использование специальных прокси-серверов для объединения соединений.
Для веб API с большим объёмом данных рассмотрите возможность использования альтернативных сред выполнения или серверов приложений с длительным временем работы.
There's a third case for PHP: run on a fastCGI interface. In this case, PHP processes are NOT destroyed after each request, and so persistent connections do persist. Set PHP_FCGI_CHILDREN << mysql's max_connections and you'll be fine.In IBM_DB2 extension v1.9.0 or later performs a transaction rollback on persistent connections at the end of a request, thus ending the transaction. This prevents the transaction block from carrying over to the next request which uses that connection if script execution ends before the transaction block does.One additional not regarding odbc_pconnect and possibly other variations of pconnect:
If the connection encounters an error (bad SQL, incorrect request, etc), that error will return with be present in odbc_errormsg for every subsequent action on that connection, even if subsequent actions don't cause another error.
For example:
A script connects with odbc_pconnect.
The connection is created on it's first use.
The script calls a query "Select * FROM Table1".
Table1 doesn't exist and odbc_errormsg contains that error.
Later(days, perhaps), a different script is called using the same parameters to odbc_pconnect.
The connection already exists, to it is reused.
The script calls a query "Select * FROM Table0".
The query runs fine, but odbc_errormsg still returns the error about Table1 not existing.
I'm not seeing a way to clear that error using odbc_ functions, so keep your eyes open for this gotcha or use odbc_connect instead.For the oci8 extension it is not true that " [...] when using transactions, a transaction block will also carry over to the next script which uses that connection if script execution ends before the transaction block does.". The oci8 extension does a rollback at the end scripts using persistent connections, thus ending the transaction. The rollback also releases locks. However any ALTER SESSION command (e.g. changing the date format) on a persistent connection will be retained over to the next script.It seems that using pg_pconnect() will not persist the temporary views/tables. So if you are trying to create temporary views/tables with the query results and then access them with the next script of the same session, you are out of luck. Those temporary view/tables are gone after each PHP script ended. One way to get around this problem is to create real view/table with session ID as part of the name and record the name&creation time in a common table. Have a garbage collection script to drop the view/table who's session is expired.If anyone ever wonders why the number of idle db process (open connections) seems to grow even though you are using persistent connections, here's why:
"You are probably using a multi-process web server such as Apache. Since
database connections cannot be shared among different processes a new
one is created if the request happen to come to a different web server
child process."To those using MySQL and finding a lot of leftover sleeping processes, take a look at MySQL's wait_timeout directive. By default it is set to 8 hours, but almost any decent production server will have been lowered to the 60 second range. Even on my testing server, I was having problems with too many connections from leftover persistent connections.