В PDO соединение можно сделать постоянным с помощью PDO::ATTR_PERSISTENT
атрибута. Согласно руководству по PHP -
Постоянные соединения не закрываются в конце сценария, но кэшируются и используются повторно, когда другой сценарий запрашивает подключение с использованием тех же учетных данных. Постоянный кэш подключений позволяет избежать накладных расходов на установление нового подключения каждый раз, когда сценарию требуется связаться с базой данных, что приводит к более быстрому веб-приложению.
В руководстве также рекомендуется не использовать постоянное соединение при использовании драйвера PDO ODBC, поскольку это может помешать процессу пула соединений ODBC.
Таким образом, по-видимому, нет никаких недостатков использования постоянного соединения в PDO, за исключением последнего случая. Тем не менее, я хотел бы знать, есть ли какие-либо другие недостатки использования этого механизма, то есть ситуация, когда этот механизм приводит к снижению производительности или что-то в этом роде.
Ответы:
Обязательно прочитайте этот ответ ниже , в котором подробно описаны способы решения проблем, изложенных здесь.
При использовании PDO существуют те же недостатки, что и с любым другим интерфейсом базы данных PHP, который выполняет постоянные соединения: если ваш скрипт неожиданно завершает работу в середине операций с базой данных, следующий запрос, который получает оставшееся соединение, будет обнаружен там, где остановился мертвый скрипт. Соединение поддерживается открытым на уровне диспетчера процессов (Apache для mod_php, текущий процесс FastCGI, если вы используете FastCGI и т. Д.), А не на уровне PHP, и PHP не сообщает родительскому процессу, чтобы соединение умирало, когда скрипт завершается ненормально.
Если мертвый скрипт заблокировал таблицы, эти таблицы будут оставаться заблокированными до тех пор, пока соединение не прекратится или следующий скрипт, который получит соединение, сам разблокирует таблицы.
Если мертвый сценарий находился в середине транзакции, он может блокировать множество таблиц до тех пор, пока не сработает таймер взаимоблокировки, и даже в этом случае таймер взаимоблокировки может уничтожить новый запрос вместо более старого запроса, вызывающего проблему.
Если мертвый скрипт находился в середине транзакции, следующий скрипт, который получает это соединение, также получает состояние транзакции. Вполне возможно (в зависимости от дизайна вашего приложения), что следующий скрипт может даже не пытаться зафиксировать существующую транзакцию, или выполнит фиксацию, когда она не должна иметь, или откатится, когда она не должна была сделать.
Это только верхушка айсберга. Все это может быть смягчено до некоторой степени, всегда пытаясь очистить после грязного соединения при каждом запросе скрипта, но это может быть проблемой в зависимости от базы данных. Если вы не определили создание соединений с базой данных как единственное узкое место в вашем скрипте (это означает, что вы выполнили профилирование кода с использованием xdebug и / или xhprof ), вам не следует рассматривать постоянные соединения как решение чего-либо.
Кроме того, большинство современных баз данных (включая PostgreSQL) имеют свои собственные предпочтительные способы выполнения пулов соединений, которые не имеют непосредственных недостатков, которые имеют обычные постоянные соединения на основе PHP.
Чтобы прояснить ситуацию, мы используем постоянные соединения на моем рабочем месте, но не по своему выбору. Мы столкнулись со странным поведением соединения, когда исходное соединение от нашего сервера приложений к нашему серверу базы данных было точно три секунды, а это должно было занимать доли доли секунды. Мы думаем, что это ошибка ядра. Мы отказались от попыток устранения неполадок, потому что это происходило случайным образом и не могло быть воспроизведено по требованию, а наши внешние ИТ не имели конкретной возможности отследить это.
Независимо от того, когда люди на складе обрабатывают несколько сотен входящих деталей, и каждая часть занимает три с половиной секунды вместо полсекунды, нам пришлось принять меры, прежде чем они похитят нас всех и заставят нас помочь им. Итак, мы включили несколько кусочков в наше доморощенное чудовище ERP / CRM / CMS и ощутили все ужасы постоянных соединений из первых рук. Нам потребовались недели, чтобы отследить все тонкие маленькие проблемы и странное поведение, которые происходили, казалось бы, наугад. Оказалось, что те фатальные ошибки раз в неделю, которые наши пользователи старательно выдавливали из нашего приложения, оставляли заблокированные таблицы, отмененные транзакции и другие неудачные состояния.
У этой истории есть одна вещь: она сломала вещи, которые мы никогда не ожидали сломать, во имя исполнения. Компромисс не стоил того, и мы с нетерпением ждем дня, когда мы сможем вернуться к обычным соединениям без бунта со стороны наших пользователей.
источник
SELECT orders.* FROM orders LEFT JOIN items USING(item_id)
register_shutdown_function()
. Если процесс умирает, соединение тоже умирает. Если это не так, соединение сбрасывается в чистое состояние (например, открытые транзакции откатываются). Если это не удается, соединение закрывается, и при следующем запросе к тому же процессу будет открыто новое. Нет необходимости демонизировать постоянные связи.mysqli_change_user
прежнему, вероятно, является лучшим обходным решением для людей, которым приходится устанавливать постоянные соединения в приложении, не предназначенном для решения проблем состояния.В ответ на проблему Чарльза выше,
От: http://www.php.net/manual/en/mysqli.quickstart.connections.php -
Распространенная жалоба на постоянные соединения заключается в том, что их состояние не сбрасывается перед повторным использованием. Например, открытые и незавершенные транзакции не откатываются автоматически. Но также изменения авторизации, которые произошли во время между помещением соединения в пул и его повторным использованием, не отражаются. Это может рассматриваться как нежелательный побочный эффект. Напротив, имя постоянное можно понимать как обещание сохранения состояния.
Расширение mysqli поддерживает обе интерпретации постоянного соединения: состояние сохраняется, и состояние сбрасывается перед повторным использованием. По умолчанию сбрасывается. Перед повторным использованием постоянного соединения расширение mysqli неявно вызывает
mysqli_change_user()
сброс состояния. Постоянное соединение отображается для пользователя, как будто оно было только что открыто. Никаких артефактов от предыдущих использований не видно.mysqli_change_user()
Функция является дорогостоящей операцией. Для лучшей производительности пользователи могут захотеть перекомпилировать расширение с установленным флагом компиляцииMYSQLI_NO_CHANGE_USER_ON_PCONNECT
.Пользователь может выбирать между безопасным поведением и лучшей производительностью. Оба являются действительными целями оптимизации. Для простоты использования безопасное поведение было установлено по умолчанию за счет максимальной производительности.
источник
Постоянные соединения - это хорошая идея, только когда требуется (относительно) много времени для соединения с вашей базой данных. В наше время это почти никогда не бывает. Самый большой недостаток постоянных подключений заключается в том, что он ограничивает количество пользователей, которые могут просматривать ваш сайт: если MySQL настроен на одновременное разрешение только 10 одновременных подключений, тогда, когда одиннадцатый человек пытается просматривать ваш сайт, он не будет работать для них. ,
PDO не управляет постоянством. Драйвер MySQL делает. Он повторно использует соединения, когда а) они доступны и хост / пользователь / пароль / база данных совпадают. Если какие-либо изменения, то он не будет повторно использовать соединение. В лучшем случае чистый эффект состоит в том, что эти ваши соединения будут запускаться и останавливаться так часто, потому что у вас есть разные пользователи на сайте, и их постоянство не приносит никакой пользы.
Главное, что нужно знать о постоянных соединениях, это то, что вы НЕ должны использовать их в большинстве веб-приложений. Они звучат заманчиво, но они опасны и в значительной степени бесполезны.
Я уверен, что на этом есть другие потоки, но постоянное соединение опасно, потому что оно сохраняется между запросами. Если, например, вы заблокируете таблицу во время запроса, а затем не сможете разблокировать ее, эта таблица останется заблокированной на неопределенный срок. Постоянные соединения также в значительной степени бесполезны для 99% ваших приложений, поскольку у вас нет возможности узнать, будет ли одно и то же соединение использоваться между различными запросами. Каждый веб-поток будет иметь свой собственный набор постоянных соединений, и вы не сможете контролировать, какой поток будет обрабатывать какие запросы.
Процедурная библиотека mysql PHP имеет функцию, посредством которой последующие вызовы mysql_connect будут возвращать ту же ссылку, а не открывать другое соединение (как можно было бы ожидать). Это не имеет ничего общего с постоянными соединениями и является специфическим для библиотеки mysql. PDO не проявляет такого поведения
Ссылка на ресурс: ссылка
В общем, вы можете использовать это как грубый "набор правил" ::
ДА , используйте постоянные соединения, если:
База данных работает на другом сервере, к которому вы обращаетесь по сети
(Одно) приложение обращается к базе данных очень часто
НЕТ , не используйте постоянные соединения, если:
Вашему приложению нужен только доступ к базе данных 100 раз в час.
У вас есть много, много веб-серверов, обращающихся к одному серверу базы данных
Использование постоянных соединений значительно быстрее, особенно если вы обращаетесь к базе данных по сети. Это не имеет большого значения, если база данных работает на той же машине, но все же немного быстрее. Однако, как следует из названия, соединение является постоянным, то есть оно остается открытым, даже если оно не используется.
Проблема в том, что в «конфигурации по умолчанию» MySQL допускает только 1000 параллельных «открытых каналов». После этого в новых соединениях будет отказано (вы можете настроить этот параметр). Поэтому, если у вас есть, скажем, 20 веб-серверов с каждыми 100 клиентами, и каждый из них имеет доступ только к одной странице в час, простая математика покажет вам, что вам потребуется 2000 параллельных подключений к базе данных. Это не сработает.
Ergo: Используйте его только для приложений с большим количеством запросов.
источник
В моих тестах у меня было время соединения более секунды с моим локальным хостом, таким образом, предполагая, что я должен использовать постоянное соединение. Дальнейшие тесты показали, что это была проблема с localhost:
Результаты теста в секундах (измеряются php microtime):
Интересно: следующий код работает так же быстро, как и 127.0.0.1:
источник
localhost
использует сокетное соединение, сокетное соединение известно как плохое на большом количестве соединенийПостоянные соединения должны значительно повысить производительность. Я не согласен со сборкой, что вы должны «избегать» упорства ..
Похоже, что приведенные выше жалобы вызваны тем, что кто-то использует таблицы MyIASM и взламывает собственные версии транзакций, захватывая блокировки таблиц. Ну, конечно, вы зашли в тупик! Используйте beginTransaction () PDO и переместите ваши таблицы в InnoDB.
источник
мне кажется, что постоянное соединение потребляет больше системных ресурсов. Может быть, тривиальная сумма, но все же ...
источник
Объяснение использования постоянных соединений, очевидно, заключается в сокращении количества соединений, которые являются довольно дорогостоящими, несмотря на то, что они намного быстрее с MySQL по сравнению с другими базами данных.
Самые первые неприятности с постоянными связями ...
Если вы создаете 1000 соединений в секунду, вы обычно не гарантируете, что они остаются открытыми в течение очень долгого времени, а Операционная система делает это. Основываясь на протоколе TCP / IP, порты нельзя перерабатывать мгновенно, а также им приходится тратить время на этап «FIN», ожидая, пока они не будут переработаны.
Вторая проблема ... использование большого количества подключений к серверу MySQL.
Многие люди просто не понимают, что вы можете увеличить переменную * max_connections * и получить более 100 одновременных соединений с MySQL, другие были побеждены старыми проблемами Linux из-за невозможности передать более 1024 соединений с MySQL.
Позволяет теперь поговорить о том, почему постоянные соединения были отключены в расширении mysqli. Несмотря на то, что вы можете неправильно использовать постоянные соединения и получить низкую производительность, что не было главной причиной. Фактическая причина в том, что вы можете получить гораздо больше проблем с этим.
Постоянные соединения были введены в PHP во всех случаях MySQL 3.22 / 3.23, когда MySQL не был таким сложным, что означает, что вы можете легко перезапускать соединения без проблем. В более поздних версиях, однако, возникло множество проблем: если вы перезапускаете соединение с незафиксированными транзакциями, у вас возникают проблемы. Если вы перезапускаете соединения с конфигурациями пользовательских наборов символов, вы снова подвергаетесь опасности, а также, возможно, трансформируете переменные для каждого сеанса.
Одна проблема с использованием постоянных соединений - это не очень хорошо масштабируется. Для тех, у кого подключено 5000 человек, вам потребуется 5000 постоянных подключений. Чтобы отменить требование постоянства, вы можете иметь возможность обслуживать 10000 человек с таким же количеством соединений, потому что они могут обмениваться индивидуальными связями, когда их нет с ними.
источник
Мне было просто интересно, будет ли частичное решение иметь пул подключений однократного использования. Вы можете потратить время на создание пула подключений, когда система используется не на пределе, до предела, раздать их и убить их, когда они завершат работу или установят тайм-аут. На заднем плане вы создаете новые соединения, когда они принимаются. В худшем случае это должно быть таким же медленным, как создание соединения без пула, при условии, что установление соединения является ограничивающим фактором?
источник