Estoy buscando un script bash bien probado (o una solución alternativa) para hacerlo, a fin de evitar que se agote max_connection. Sé que está luchando contra los síntomas, pero realmente necesito ese script como una solución a corto plazo.
Estoy buscando un script bash bien probado (o una solución alternativa) para hacerlo, a fin de evitar que se agote max_connection. Sé que está luchando contra los síntomas, pero realmente necesito ese script como una solución a corto plazo.
Respuestas:
echa un vistazo al comando pt-kill del kit de herramientas de percona .
y ... comience a monitorear su sistema: munin , cactus con mejores plantillas de cactus para mysql , cualquier cosa para que tenga una idea de lo que está sucediendo. el registro de consultas lentas de mysql también será una buena idea.
Si tiene MySQL 5.1 donde la lista de procesos está en INFORMATION_SCHEMA, puede hacer esto para generar los comandos KILL QUERY en masa desde el cliente mysql para consultas que se ejecutan más de 20 minutos (1200 segundos):
SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery
FROM information_schema.processlist WHERE user<>'system user'
AND time >= 1200\G
Puede hacer cláusulas WHERE en el campo INFO para buscar una consulta específica, el campo TIME en consultas de ejecución prolongada o el campo DB en una base de datos específica.
Si es root @ localhost, debe tener todos los privilegios para ejecutar esto de la siguiente manera
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
Puede crontab esto de la siguiente manera:
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
Aquí hay otra variación:
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
Por cierto, no tiene que especificar un myDB ya que leí explícitamente information_schema.processlist como un nombre de tabla completamente calificado.
Aquí hay una demostración de lo que debería ver. Para este ejemplo, haré eco del comando KILL de todos los procesos cuyo tiempo> 20000 segundos:
[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@***** ~]#
He estado haciendo esta técnica durante los últimos 5 años. De hecho, envié esta respuesta al DBA StackExchange el año pasado y fue aceptada .
Encontré el siguiente código recortado aquí :
Actualización 2013-01-14: Hubo una sugerencia anónima de que esto es potencialmente peligroso y también puede matar los procesos de replicación. Así que use bajo su propio riesgo:
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 en adelante puede usar la variable max_execution_time para hacer esto automáticamente para todas las consultas de lectura "SELECCIONAR".
¡No probaría las soluciones bash si te gusta el tiempo de actividad!
Si tiene acceso al código, puede establecer el tiempo de ejecución máximo en las instrucciones SELECT utilizando el método descrito aquí :
SELECT
MAX_EXECUTION_TIME = 1000 --in milliseconds
*
FROM table;
De lo contrario, en el servidor:
/programming/415905/how-to-set-a-maximum-execution-time-for-a-mysql-query
Instalar pt-kill:
$ wget percona.com/get/pt-kill
Tome una instantánea de su lista de procesos:
$ mysql -u root -B -pmyreallyimportantpassword -e "show processlist;" > processlist.txt
Prueba pt-kill en la instantánea:
$ ./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
Asegúrese de que las reglas del partido se adapten a su caso. Estos anteriores matarán todas las declaraciones de ejecución durante 45 segundos. Una vez que esté seguro, modifique y ejecute este comando para ejecutar la declaración en un intervalo de 10 segundos:
$ ./pt-kill -u root -p myreallyimportantpassword --busy-time 45 --kill-busy-commands 'Execute' --victims all --interval 10 --kill