Szukam dobrze przetestowanego skryptu bash (lub alternatywnego rozwiązania), aby to zrobić, aby uniknąć wyczerpania max_connection. Wiem, że walczy z objawami, ale naprawdę potrzebuję takiego skryptu jako rozwiązania krótkoterminowego.
Szukam dobrze przetestowanego skryptu bash (lub alternatywnego rozwiązania), aby to zrobić, aby uniknąć wyczerpania max_connection. Wiem, że walczy z objawami, ale naprawdę potrzebuję takiego skryptu jako rozwiązania krótkoterminowego.
Odpowiedzi:
sprawdź komendę pt-kill z zestawu narzędzi Percona .
i ... zacznij monitorować swój system - munin , kaktusy z lepszymi szablonami kaktusów dla mysql , wszystko, żebyś miał pojęcie, co się dzieje. dobrym pomysłem będzie także rejestrowanie powolnych zapytań mysql.
Jeśli masz MySQL 5.1, w którym lista procesów znajduje się w pliku INFORMACJE_SCHEMA, możesz to zrobić, aby wygenerować polecenia KILL QUERY zbiorczo z poziomu klienta mysql dla zapytania trwającego dłużej niż 20 minut (1200 sekund):
SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery
FROM information_schema.processlist WHERE user<>'system user'
AND time >= 1200\G
Możesz wykonać klauzule WHERE w polu INFO, aby wyszukać określone zapytanie, pole TIME w przypadku zapytań długo działających lub pole DB w przypadku określonej bazy danych.
Jeśli jesteś rootem @ localhost, powinieneś mieć pełne uprawnienia do uruchamiania tego w następujący sposób
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
Możesz to zrobić w następujący sposób:
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
Oto kolejna odmiana:
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
BTW Nie określiłeś myDB, ponieważ wyraźnie odczytałem z information_schema.processlist jako w pełni kwalifikowaną tablename.
Oto pokaz tego, co powinieneś zobaczyć. W tym przykładzie powtórzę polecenie KILL wszystkich procesów, których czas> 20000 sekund:
[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@***** ~]#
Robię tę technikę przez ostatnie 5 lat. W rzeczywistości przesłałem tę odpowiedź do DBA StackExchange w zeszłym roku i została zaakceptowana .
Znalazłem następujący kod-snipped tutaj :
Aktualizacja 14.01.2013: Anonimowo zasugerowano, że jest to potencjalnie niebezpieczne i może również zabić procesy replikacji. Korzystaj więc na własne ryzyko:
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 i nowsze, możesz użyć zmiennej max_execution_time, aby zrobić to automatycznie dla wszystkich zapytań odczytu „SELECT”.
Nie spróbowałbym rozwiązań bash, jeśli lubisz czas pracy!
Jeśli masz dostęp do kodu, możesz faktycznie ustawić maksymalny czas wykonywania instrukcji SELECT przy użyciu metody opisanej tutaj :
SELECT
MAX_EXECUTION_TIME = 1000 --in milliseconds
*
FROM table;
W przeciwnym razie na serwerze:
/programming/415905/how-to-set-a-maximum-execution-time-for-a-mysql-query
Zainstaluj pt-kill:
$ wget percona.com/get/pt-kill
Zrób migawkę swojej listy procesów:
$ mysql -u root -B -pmyreallyimportantpassword -e "show processlist;" > processlist.txt
Test pt-kill na migawce:
$ ./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
Upewnij się, że zasady dopasowania odpowiadają twojej sprawie. Powyższe zabije wszystkie instrukcje wykonania w ciągu 45 sekund. Gdy masz pewność, zmodyfikuj i uruchom tę komendę, aby wykonać instrukcję w odstępie 10 sekund:
$ ./pt-kill -u root -p myreallyimportantpassword --busy-time 45 --kill-busy-commands 'Execute' --victims all --interval 10 --kill