Подтвердить что ты не робот

Список участников MySql, заполненный записями "Сон", приводящих к "Слишком много подключений"?

Я хотел бы попросить вашей помощи по давней проблеме с соединениями php/mysql.

Каждый раз, когда я выполняю команду "SHOW PROCESSLIST", она показывает мне около 400 незанятых (Status: Sleep) подключений к серверу базы данных, возникающих на наших 5 веб-серверах.

Это никогда не было большой проблемой (и я не нашел быстрого решения), пока в последнее время количество трафика не увеличилось, и с тех пор MySQL неоднократно сообщает о проблемах "ко многим соединениям", даже если 350+ этих соединений находятся в "спящем режиме" государство. Кроме того, сервер не может получить соединение MySQL, даже если к этому же серверу есть спящие соединения.

Все эти соединения исчезают при переустановке сервера Apache.

Код PHP, используемый для создания соединений с БД, использует обычный модуль "mysql", модуль "mysqli", PEAR :: DB и Zend Framework Db Adapter. (Разные проекты). Ни один из проектов не использует постоянные соединения.

Повышение лимита соединения возможно, но не кажется хорошим решением, поскольку сейчас оно составляет 450, и в любом случае в каждый момент времени существует только 20-100 "реальных" соединений.

Мой вопрос:

Почему в состоянии сна столько подключений и как я могу это предотвратить?

- Обновление:

Число запросов Apache, выполняемых за один раз, никогда не превышает 50 одновременных запросов, поэтому я думаю, что есть проблема с закрытием соединения, или apache держит порт открытым без присоединенного phpscript или чего-то еще (?)

my.cnf, если это полезно:

innodb_buffer_pool_size = 1024M

max_allowed_packet = 5M
net_buffer_length = 8K

read_buffer_size = 2M
read_rnd_buffer_size = 8M

query_cache_size = 512M
myisam_sort_buffer_size = 128M

max_connections = 450
thread_cache = 50
key_buffer_size = 1280M
join_buffer_size = 16M

table_cache = 2048
sort_buffer_size = 64M
tmp_table_size = 512M
max_heap_table_size = 512M

thread_concurrency = 8

log-slow-queries = /daten/mysql-log/slow-log
long_query_time = 1
log_queries_not_using_indexes

innodb_additional_mem_pool_size = 64M
innodb_log_file_size = 64M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table
4b9b3361

Ответ 1

В принципе, вы получаете соединения в состоянии "Сон", когда:

  • PHP script подключается к MySQL
  • Выполняются некоторые запросы
  • тогда PHP скрипт делает некоторые вещи, которые требуют времени
    • без отсоединения от DB
  • и, наконец, заканчивается PHP скрипт
    • что означает, что он отключается от сервера MySQL

Таким образом, вы, как правило, получаете много процессов в состоянии "Сон", когда у вас много процессов PHP, которые остаются на связи, и фактически ничего не делают на стороне базы данных.

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


Другое дело, что я часто вижу, когда на сервере есть некоторая загрузка:

  • В Apache все больше запросов
    • что означает, что многие страницы генерируют
  • Каждый PHP script, чтобы сгенерировать страницу, подключается к БД и выполняет некоторые запросы
  • Эти запросы занимают все больше времени, так как загрузка на сервере БД увеличивается.
  • Это означает, что все процессы продолжают стекировать.

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

Ответ 2

Увеличение количества max-соединений не решит проблему.

Мы столкнулись с такой же ситуацией на наших серверах. Это то, что происходит

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

Вы можете установить для MySQL interactive_timeout, по умолчанию это 28800 (8 часов) до 1 часа

SET interactive_timeout=3600

Ответ 3

Прежде чем увеличивать переменную max_connections, вы должны проверить, сколько у вас неинтерактивных соединений, запустив команду show processlist.

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

  • Чтобы показать значение wait_timeout:

ПОКАЗАТЬ СЕССИИ ПЕРЕМЕННЫЕ, КАК 'wait_timeout';

+ --------------- + ------- +

| Переменное_имя | Значение |

+ --------------- + ------- +

| wait_timeout | 28800 |

+ --------------- + ------- +

значение в секундах, это означает, что неинтерактивное соединение еще до 8 часов.

  • Чтобы изменить значение переменной "wait_timeout":

SET session wait_timeout = 600; Запрос в порядке, затронуто 0 строк (0,00 с)

Через 10 минут, если спящее соединение все еще спит, mysql или MariaDB прерывают это соединение.

Ответ 4

Итак, я запускал 300 PHP-процессов симулятивно и получал скорость от 60 до 90 в секунду (мой процесс включает в себя 3х запросов). Я поднял его до 400, и это упало примерно до 40-50 в секунду. Я бросил его до 200 и вернулся к 60 и 90 годам!

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

Ответ 5

Вышеуказанные решения, например, выполнить запрос

SET session wait_timeout=600;

Работает только до перезапуска mysql. Для постоянного решения отредактируйте mysql.conf и добавьте после [mysqld]:

wait_timeout=300
interactive_timeout = 300

Где 300 - это количество секунд, которое вы хотите.

Ответ 6

Хорошо, поэтому, пробовав каждое решение для решения этих точных проблем в блоге Wordpress, я мог бы сделать что-то действительно глупое или гениальное... Не зная, почему существует увеличение соединений Mysql, я использовал php script ниже в моем заголовке, чтобы убить все спальные процессы.

Поэтому каждый посетитель моего сайта помогает убивать спальные процессы.

<?php
$result = mysql_query("SHOW processlist");
while ($myrow = mysql_fetch_assoc($result)) {
if ($myrow['Command'] == "Sleep") {
mysql_query("KILL {$myrow['Id']}");}
}
?>