Je recherche un script bash bien testé (ou une solution alternative) pour le faire, afin d'éviter que max_connection ne soit épuisé. Je sais qu'il combat les symptômes, mais j'ai vraiment besoin d'un tel script comme solution à court terme.
Je recherche un script bash bien testé (ou une solution alternative) pour le faire, afin d'éviter que max_connection ne soit épuisé. Je sais qu'il combat les symptômes, mais j'ai vraiment besoin d'un tel script comme solution à court terme.
Réponses:
consultez la commande pt-kill de la boîte à outils percona .
et .. commencez à surveiller votre système - munin , cacti avec de meilleurs modèles de cactus pour mysql , n'importe quoi pour que vous ayez une idée de ce qui se passe. la journalisation des requêtes lentes mysql sera également une bonne idée.
Si vous avez MySQL 5.1 où la liste de processus se trouve dans INFORMATION_SCHEMA, vous pouvez le faire pour générer les commandes KILL QUERY en bloc à partir du client mysql pour une requête de plus de 20 minutes (1200 secondes):
SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery
FROM information_schema.processlist WHERE user<>'system user'
AND time >= 1200\G
Vous pouvez faire des clauses WHERE sur le champ INFO pour rechercher une requête spécifique, le champ TIME sur les requêtes de longue durée ou le champ DB sur une base de données spécifique.
Si vous êtes root @ localhost, vous devriez avoir tous les privilèges pour l'exécuter comme suit
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
Vous pouvez créer ceci comme suit:
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
Voici une autre 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
BTW Vous n'avez pas spécifié de myDB car j'ai explicitement lu dans information_schema.processlist un nom de table complet.
Voici une démonstration de ce que vous devriez voir. Pour cet exemple, je ferai écho à la commande KILL de tous les processus dont le temps> 20000 secondes:
[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@***** ~]#
Je pratique cette technique depuis 5 ans. En fait, j'ai soumis cette réponse au DBA StackExchange l'année dernière et elle a été acceptée .
J'ai trouvé le code suivant coupé ici :
Mise à jour 2013-01-14: Il y avait une indication anonyme que cela est potentiellement dangereux et peut également tuer les processus de réplication. Utilisez donc à vos risques et périls:
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 et versions ultérieures, vous pouvez utiliser la variable max_execution_time pour que cela se fasse automatiquement pour toutes les requêtes de lecture "SELECT".
Je n'essaierais pas les solutions bash si vous aimez la disponibilité!
Si vous avez accès au code, vous pouvez réellement définir le temps d'exécution maximal sur les instructions SELECT à l'aide de la méthode décrite ici :
SELECT
MAX_EXECUTION_TIME = 1000 --in milliseconds
*
FROM table;
Sinon, sur le serveur:
/programming/415905/how-to-set-a-maximum-execution-time-for-a-mysql-query
Installez pt-kill:
$ wget percona.com/get/pt-kill
Prenez un instantané de votre liste de processus:
$ mysql -u root -B -pmyreallyimportantpassword -e "show processlist;" > processlist.txt
Testez pt-kill sur l'instantané:
$ ./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
Assurez-vous que les règles du match conviennent à votre cas. Celles ci-dessus tueront toutes les instructions Execute en 45 secondes. Une fois que vous êtes sûr, modifiez et exécutez cette commande pour exécuter l'instruction à un intervalle de 10 secondes:
$ ./pt-kill -u root -p myreallyimportantpassword --busy-time 45 --kill-busy-commands 'Execute' --victims all --interval 10 --kill