Sto cercando uno script bash ben collaudato (o una soluzione alternativa) per farlo, al fine di evitare che max_connection sia esaurito. So che sta combattendo i sintomi, ma ha davvero bisogno di una sceneggiatura come soluzione a breve termine.
Sto cercando uno script bash ben collaudato (o una soluzione alternativa) per farlo, al fine di evitare che max_connection sia esaurito. So che sta combattendo i sintomi, ma ha davvero bisogno di una sceneggiatura come soluzione a breve termine.
Risposte:
controlla il comando pt-kill dal toolkit percona .
e .. inizia a monitorare il tuo sistema: munin , cactus con migliori template di cactus per mysql , qualsiasi cosa in modo da avere un'idea di cosa stia succedendo. anche la registrazione delle query lente di mysql sarà una buona idea.
Se hai MySQL 5.1 in cui l'elenco dei processi si trova in INFORMATION_SCHEMA, puoi farlo per generare in blocco i comandi KILL QUERY dall'interno del client mysql per query che durano più di 20 minuti (1200 secondi):
SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery
FROM information_schema.processlist WHERE user<>'system user'
AND time >= 1200\G
È possibile eseguire clausole WHERE sul campo INFO per cercare una query specifica, il campo TIME su query a esecuzione prolungata o il campo DB su un database specifico.
Se sei root @ localhost, dovresti avere i privilegi completi per eseguire questo come segue
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
Puoi crontab questo come segue:
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
Ecco un'altra variante:
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
A proposito, non hai specificato un myDB poiché ho letto esplicitamente da information_schema.processlist come un nome tabl completo.
Ecco una dimostrazione di ciò che dovresti vedere. Per questo esempio, farò eco al comando KILL di tutti i processi il cui tempo> 20000 secondi:
[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@***** ~]#
Faccio questa tecnica da 5 anni. In effetti, ho inviato questa risposta al DBA StackExchange lo scorso anno ed è stata accettata .
Ho trovato il seguente frammento di codice qui :
Aggiornamento 2013-01-14: c'è stato un indizio anonimo del fatto che questo è potenzialmente pericoloso e può anche uccidere i processi di replica. Quindi utilizzare a proprio rischio:
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
Da MySQL 5.7 in poi puoi usare la variabile max_execution_time per farlo automaticamente per tutte le query di lettura "SELECT".
Non proverei soluzioni bash se ti piacciono i tempi di attività!
Se hai accesso al codice, puoi effettivamente impostare il tempo massimo di esecuzione sulle istruzioni SELECT usando il metodo descritto qui :
SELECT
MAX_EXECUTION_TIME = 1000 --in milliseconds
*
FROM table;
Altrimenti, sul server:
/programming/415905/how-to-set-a-maximum-execution-time-for-a-mysql-query
Installa pt-kill:
$ wget percona.com/get/pt-kill
Scatta un'istantanea del tuo elenco di processi:
$ mysql -u root -B -pmyreallyimportantpassword -e "show processlist;" > processlist.txt
Prova pt-kill sull'istantanea:
$ ./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
Assicurati che le regole della partita siano adatte al tuo caso. Queste sopra uccideranno tutte le istruzioni Execute per 45 secondi. Dopo esserti assicurato, modifica ed esegui questo comando per eseguire l'istruzione a intervalli di 10 secondi:
$ ./pt-kill -u root -p myreallyimportantpassword --busy-time 45 --kill-busy-commands 'Execute' --victims all --interval 10 --kill