Я ищу хорошо протестированный сценарий bash (или альтернативное решение) для этого, чтобы избежать исчерпания max_connection. Я знаю, что он борется с симптомами, но действительно нужен такой сценарий как краткосрочное решение.
проверять, выписываться pt-kill команда из набор инструментов percona.
и .. начать мониторинг вашей системы - Мунин, кактусы с участием лучшие шаблоны cacti для mysql, что угодно, чтобы вы поняли, что происходит. ведение журнала медленных запросов mysql также будет хорошей идеей.
Если у вас есть MySQL 5.1, где список процессов находится в INFORMATION_SCHEMA, вы можете сделать это, чтобы массово сгенерировать команды KILL QUERY из клиента mysql для запроса, выполняющегося дольше 20 минут (1200 секунд):
SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery
FROM information_schema.processlist WHERE user<>'system user'
AND time >= 1200\G
Вы можете использовать предложения WHERE для поля INFO для поиска определенного запроса, поля TIME для длительных запросов или поля DB для конкретной базы данных.
Если вы root @ localhost, у вас должны быть полные права для запуска, как показано ниже.
SECONDS_TOO_LONG=1200
KILLPROC_SQLSTMT="SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" | mysql -uroot -ppassword
Вы можете настроить это следующим образом:
SECONDS_TOO_LONG=1200
QUERIES_RUNNING_TOO_LONG=`mysql -uroot -ppassword -ANe"SELECT COUNT(1) FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"`
if [ ${QUERIES_RUNNING_TOO_LONG} -gt 0 ]
then
KILLPROC_SQLSTMT="SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" | mysql -uroot -ppassword
fi
Вот еще один вариант:
SECONDS_TOO_LONG=1200
QUERIES_RUNNING_TOO_LONG=`mysql -uroot -ppassword -ANe"SELECT COUNT(1) FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"`
if [ ${QUERIES_RUNNING_TOO_LONG} -gt 0 ]
then
KILLPROC_SQLSTMT="SELECT CONCAT('KILL QUERY ',id,';') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" > /tmp/kill_log_queries.sql
mysql -uroot -ppassword < /tmp/kill_log_queries.sql
fi
Кстати, вы не указали myDB, поскольку я явно читаю из information_schema.processlist как полное имя таблицы.
Вот демонстрация того, что вы должны увидеть. В этом примере я повторю команду KILL для всех процессов, время которых> 20000 секунд:
[root@***** ~]# mysql `lwdba_connect` -ANe"SELECT GROUP_CONCAT('KILL ',id,'; ' SEPARATOR ' ') FROM information_schema.processlist WHERE time > 25000 AND user<>'system user';"
+----------------------------------------------------+
| KILL 180186; KILL 180141; KILL 176419; KILL 3; |
+----------------------------------------------------+
[root@***** ~]#
Я занимаюсь этой техникой последние 5 лет. Фактически, я отправил этот ответ в DBA StackExchange в прошлом году, и он был принят..
Я нашел следующий фрагмент кода Вот:
Обновить 2013-01-14: Был анонимный намек на то, что это потенциально опасно и также может убить процессы репликации. Так что используйте на свой страх и риск:
mysql -e 'show processlist\G' |\
egrep -b5 'Time: [0-9]{2,}' |\
grep 'Id:' |\
cut -d':' -f2 |\
sed 's/^ //' |\
while read id
do
mysql -e "kill $id;"
done
Начиная с MySQL 5.7 вы можете использовать переменную max_execution_time, чтобы сделать это автоматически для всех запросов чтения «SELECT».
Я бы не стал пробовать решения на bash, если вам нравится время безотказной работы!
Если у вас есть доступ к коду, вы можете установить максимальное время выполнения для операторов SELECT, используя описанный метод. Вот :
SELECT
MAX_EXECUTION_TIME = 1000 --in milliseconds
*
FROM table;
В противном случае на сервере:
https://stackoverflow.com/questions/415905/how-to-set-a-maximum-execution-time-for-a-mysql-query
Установите pt-kill:
$ wget percona.com/get/pt-kill
Сделайте снимок своего списка процессов:
$ mysql -u root -B -pmyreallyimportantpassword -e "show processlist;" > processlist.txt
Протестируйте pt-kill на снимке:
$ ./pt-kill --test-matching processlist.txt --busy-time 45 --kill-busy-commands 'Execute' --victims all --print
# 2019-02-25T17:34:37 KILL 45710302 (Execute 374 sec) SELECT\n\tCOUNT(DISTINCT(LP.sessionId))\nFROM lp_traffic LP\nINNER JOIN orders O ON O.orderId = LP.order
# 2019-02-25T17:34:37 KILL 45713515 (Execute 67 sec) SELECT \n\tCOUNT(DISTINCT(CASE WHEN T.response = 'SUCCESS' AND T.isVoid = 0 AND (T.txnType IN
Убедитесь, что правила матча подходят для вашего случая. Это приведет к уничтожению всех операторов Execute в течение 45 секунд. Убедившись, что вы уверены, измените и запустите эту команду, чтобы выполнить инструкцию с интервалом в 10 секунд:
$ ./pt-kill -u root -p myreallyimportantpassword --busy-time 45 --kill-busy-commands 'Execute' --victims all --interval 10 --kill