Каковы недостатки использования постоянного соединения в PDO

В PDO соединение может быть выполнено постоянно, используя атрибут PDO::ATTR_PERSISTENT . Согласно руководству php

Стойкие соединения не закрываются в конце скрипта, но кэшируются и повторно используются, когда другой скрипт запрашивает соединение с использованием тех же учетных данных. Постоянный кеш подключений позволяет избежать накладных расходов на установление нового соединения каждый раз, когда скрипт должен разговаривать с базой данных, что приводит к более быстрому веб-приложению.

В руководстве также рекомендуется не использовать постоянное соединение при использовании драйвера PDO ODBC, поскольку это может помешать процессу объединения соединений ODBC.

Таким образом, по-видимому, нет никаких недостатков в использовании постоянного соединения в PDO, за исключением последнего случая. Тем не менее, я хотел бы знать, есть ли другие недостатки использования этого механизма, т. Е. Ситуация, когда этот механизм приводит к ухудшению производительности или тому подобному.

Solutions Collecting From Web of "Каковы недостатки использования постоянного соединения в PDO"

Пожалуйста, не забудьте прочитать этот ответ ниже , в котором подробно описаны способы устранения проблем, описанных здесь.


Те же недостатки существуют с использованием PDO, как и с любым другим интерфейсом базы данных PHP, который выполняет постоянные соединения: если ваш сценарий неожиданно заканчивается в середине операций с базой данных, следующий запрос, который получает соединение слева, будет подниматься там, где остановился мертвый сценарий. Соединение открыто на уровне диспетчера процессов (Apache для mod_php, текущий процесс FastCGI, если вы используете FastCGI и т. Д.), А не на уровне PHP, а PHP не сообщает родительскому процессу, чтобы соединение замирало, когда сценарий прерывается ненормально.

Если мертвый сценарий заблокировал таблицы, эти таблицы останутся заблокированными до тех пор, пока соединение не умрет, или следующий скрипт, который получает соединение, не разблокирует сами таблицы.

Если мертвый сценарий находился в середине транзакции, это может блокировать множество таблиц до тех пор, пока таймер блокировки не начнет работать, и даже тогда таймер взаимоблокировки может убить новый запрос вместо старого запроса, вызывающего проблему.

Если мертвый скрипт находился в середине транзакции, следующий скрипт, который получает это соединение, также получает состояние транзакции. Очень возможно (в зависимости от вашего дизайна приложения), что следующий скрипт на самом деле никогда не попытается зафиксировать существующую транзакцию или не будет зафиксирован, когда этого не должно быть, или откат, когда этого не должно быть.

Это только верхушка айсберга. Все это можно смягчить, пытаясь очистить после грязного соединения по каждому запросу сценария, но это может быть болью в зависимости от базы данных. Если вы не определили создание соединений с базой данных как одну вещь, которая является узким местом в вашем скрипте (это означает, что вы сделали профилирование кода с использованием xdebug и / или xhprof ), вы не должны рассматривать постоянные соединения как решение чего-либо.

Кроме того, большинство современных баз данных (в том числе PostgreSQL) имеют свои собственные предпочтительные способы выполнения пула соединений, которые не имеют непосредственных недостатков, которые делают простые постоянные соединения на основе ванильных PHP.


Чтобы прояснить ситуацию, мы используем постоянные подключения на моем рабочем месте, но не по своему выбору. Мы столкнулись с странным поведением подключения, когда начальное соединение с нашего сервера приложений на нашем сервере базы данных занимало ровно три секунды, когда оно должно было занимать часть доли секунды. Мы считаем, что это ошибка ядра. Мы отказались от попыток устранить его, потому что это произошло случайным образом и не могло быть воспроизведено по требованию, и наши аутсорсинговые ИТ не имели конкретной возможности отслеживать его.

Несмотря на это, когда люди на складе обрабатывают несколько сотен входящих частей, и каждая часть занимает три с половиной секунды вместо половины секунды, мы должны были принять меры, прежде чем они похитили нас всех и заставили нас помочь им. Таким образом, мы перевернули несколько бит в нашем самодельном оригинале ERP / CRM / CMS и испытали все ужасы постоянных соединений из первых рук. Нам потребовались недели, чтобы отследить все тонкие небольшие проблемы и причудливое поведение, которое казалось случайным образом. Оказалось, что эти раз в неделю фатальные ошибки, которые наши пользователи усердно вытеснили из нашего приложения, оставляют заблокированные столы, заброшенные транзакции и другие неудачные неуклюжие состояния.

У этой рыдающей истории есть точка: она сломала вещи, которые мы никогда не ожидали сломать, во имя производительности. Компромисс не стоил того, и мы с нетерпением ждем того дня, когда мы сможем вернуться к нормальным соединениям без буйства наших пользователей.

В ответ на вышеизложенную проблему Чарльза,

От: http://www.php.net/manual/en/mysqli.quickstart.connections.php

Обычные жалобы на постоянные соединения состоят в том, что их состояние не сбрасывается перед повторным использованием. Например, открытые и незавершенные транзакции автоматически не откатываются. Но также, изменения авторизации, которые произошли во время между подключением в пул и повторным использованием, не отражаются. Это можно рассматривать как нежелательный побочный эффект. Напротив, постоянное имя можно понимать как обещание, что государство сохраняется.

Расширение mysqli поддерживает как интерпретации постоянного соединения: состояние сохраняется, так и сброс состояния перед повторным использованием. По умолчанию сбрасывается. Перед mysqli_change_user() использованием постоянного соединения расширение mysqli неявно вызывает mysqli_change_user() для сброса состояния. Постоянное соединение появляется пользователю так, как будто оно только что открыто. Никакие артефакты из предыдущих обычаев не видны.

Функция mysqli_change_user() – дорогостоящая операция. Для лучшей производительности пользователи могут захотеть перекомпилировать расширение с установленным параметром MYSQLI_NO_CHANGE_USER_ON_PCONNECT .

Пользователю предоставляется возможность выбирать между безопасным поведением и максимальной производительностью. Оба являются действительными целями оптимизации. Для удобства использования безопасное поведение было сделано по умолчанию за счет максимальной производительности.

В моих тестах у меня было время подключения более чем на секунду до моего локального хоста, поэтому, предполагая, что я должен использовать постоянное соединение. Дальнейшие тесты показали, что это проблема с «localhost»:

Результаты тестов в секундах (измеренные с помощью php microtime):

  • веб-сайт: connectDB: 0.0038912296295166
  • localhost: connectDB: 1.0214691162109 (более одной секунды: не используйте localhost!)
  • 127.0.0.1: connectDB: 0.00097203254699707

Интересно: следующий код работает так же быстро, как 127.0.0.1:

 $host = gethostbyname('localhost'); // echo "<p>$host</p>"; $db = new PDO("mysql:host=$host;dbname=" . DATABASE . ';charset=utf8', $username, $password, array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); 

Стойкие соединения – хорошая идея только тогда, когда требуется (относительно) долгое время для подключения к вашей базе данных. В наше время это почти никогда не бывает. Самый большой недостаток постоянных подключений заключается в том, что он ограничивает количество пользователей, которых вы можете просматривать на своем сайте: если MySQL настроен на одновременное использование только 10 одновременных подключений, то когда 11-й человек пытается просмотреть ваш сайт, он не будет работать для них ,

PDO не справляется с сохранением. Драйвер MySQL делает это. Он повторно использует соединения, когда они доступны, и совпадение между хостом / пользователем / паролем / базой данных. Если какое-либо изменение, то оно не будет повторно использовать соединение. Лучший сетевой эффект – это то, что эти соединения, которые у вас есть, будут запущены и остановлены так часто, потому что у вас есть разные пользователи на сайте и делают их постоянными, не приносит никакой пользы.

Главное, что нужно знать о постоянных соединениях, – это то, что вы не должны использовать их в большинстве веб-приложений. Они звучат соблазнительно, но они опасны и практически бесполезны.

Я уверен, что в этом есть другие темы, но постоянное соединение опасно, потому что оно сохраняется между запросами. Если, например, вы блокируете таблицу во время запроса и затем не можете разблокировать, тогда эта таблица будет оставаться заблокированной на неопределенный срок. Стойкие соединения также практически бесполезны для 99% ваших приложений, потому что у вас нет способа узнать, будет ли одно и то же соединение использоваться между различными запросами. Каждый веб-поток будет иметь собственный набор постоянных подключений, и у вас нет способа контролировать, какой поток будет обрабатывать эти запросы.

В процедурной mysql-библиотеке PHP есть функция, при которой последующие вызовы mysql_connect возвращают ту же ссылку, а не открывают другое соединение (как и следовало ожидать). Это не имеет ничего общего с постоянными подключениями и специфично для библиотеки mysql. PDO не проявляет такого поведения


Ссылка ресурса: ссылка

В целом вы можете использовать это как грубый «набор правил» ::

ДА , используйте постоянные соединения, если:

  • Доступ к базе данных осуществляется только несколькими приложениями / пользователями, то есть вы не будете приводить к 200 открытым (но, вероятно, незанятым) подключениям, потому что на одном и том же хосте есть 200 разных пользователей.
  • База данных работает на другом сервере, к которому вы обращаетесь по сети

  • Приложение (одно) очень часто обращается к базе данных

НЕТ , не используйте постоянные соединения, если:

  • Вашему приложению требуется только доступ к базе данных 100 раз в час.

  • У вас много, много веб-серверов, обращающихся к одному серверу базы данных

Использование постоянных соединений значительно быстрее, особенно если вы обращаетесь к базе данных по сети. Это не имеет большого значения, если база данных работает на одной машине, но она все еще немного быстрее. Однако, как говорится в названии, соединение является постоянным, то есть оно остается открытым, даже если оно не используется.

Проблема в том, что в «конфигурации по умолчанию» MySQL допускает только 1000 параллельных «открытых каналов». После этого новые соединения будут отклонены (вы можете настроить эту настройку). Поэтому, если у вас есть – скажем, 20 веб-серверов с каждым 100 Клиентами на них, и каждый из них имеет только один доступ к странице в час, простая математика покажет вам, что вам потребуется 2000 параллельных подключений к базе данных. Это не сработает.

Ergo: Используйте его только для приложений с большим количеством запросов.

Постоянное подключение должно дать значительное повышение производительности. Я не согласен с тем, что вы должны «избегать» настойчивости.

Похоже, что жалобы, приведенные выше, управляются кем-то, использующим таблицы MyIASM, и взламывают их собственные версии транзакций, захватывая столовые замки. Ну, конечно, вы зашли в тупик! Используйте startTransaction () PDO и переместите свои таблицы в InnoDB ..

мне кажется, что постоянная связь будет потреблять больше системных ресурсов. Может быть, тривиальная сумма, но все же …

Объяснение использования постоянных соединений, очевидно, снижает количество подключений, которые являются довольно дорогостоящими, несмотря на то, что они значительно быстрее с MySQL по сравнению с другими базами данных.

Самая первая проблема с постоянными соединениями …

Если вы создаете 1000 соединений в секунду, вы, как правило, не гарантируете, что он остается открытым в течение очень долгого времени, но Operation System делает это. На основе протокола TCP / IP порты не могут быть переработаны мгновенно и также должны инвестировать некоторое время в стадию «FIN», прежде чем они могут быть переработаны.

Вторая проблема … использование большого количества подключений к серверу MySQL.

Многие люди просто не понимают, что вы можете увеличить переменную * max_connections * и получить более 100 параллельных соединений с MySQL. Другие были избиты более старыми проблемами Linux из-за невозможности передать более 1024 соединений с MySQL.

Позволяет говорить о том, почему постоянные соединения были отключены в расширении mysqli. Несмотря на то, что вы можете злоупотреблять постоянными соединениями и получать плохую производительность, что не является основной причиной. Фактическая причина – вы можете получить гораздо больше проблем с ней.

Постоянные соединения были помещены в PHP на протяжении всего времени MySQL 3.22 / 3.23, когда MySQL не был настолько сложным, что означает, что вы можете легко перерабатывать соединения без проблем. В более поздних версиях возникло множество проблем. Если вы переработаете соединение, в котором есть незавершенные транзакции, вы попадаете в неприятности. Если вы перерабатываете соединения с настраиваемыми настройками набора символов, вы снова оказываетесь в опасности, а также, возможно, преобразуетесь в переменные сеанса.

Одна проблема с использованием постоянных подключений – это не очень хорошо масштабируется. Для тех, кто подключен к 5000 человек, вам понадобятся 5000 постоянных подключений. Чтобы избежать необходимости сохранения, вы можете иметь возможность обслуживать 10000 человек с одинаковым количеством соединений, потому что они могут обмениваться личными связями, когда они не с ними.

Я просто задавался вопросом, будет ли частичное решение иметь пул соединений с одноразовым соединением. Вы могли бы потратить время на создание пула соединений, когда система работает с низким уровнем использования, до предела, передает их и убивает их, когда они завершены или тайм-аут. В фоновом режиме вы создаете новые соединения, поскольку они принимаются. В худшем случае это должно быть так же медленно, как создание соединения без пула, если предположить, что установление ссылки является ограничивающим фактором?