2011-11-24 62 views
5

Hola, tengo problemas en mi servidor en el momento porque algunas de las consultas MySQL tardan mucho tiempo en ejecutarse y acaparan los recursos en el servidor.De todos modos para limitar el tiempo de ejecución de consultas MySQL?

Ya estoy en el proceso de optimizar todas las consultas para mejorar el rendimiento, pero como usamos una gran cantidad de aplicaciones de terceros en el servidor que usa mysql, esperaba establecer una salvaguarda para evitar problemas futuros. .

Lo que necesito es algo que pueda implementar en todo el servidor y que se aplique a todas las consultas, pero con la posibilidad de anularlo por consulta para algunos de los informes más complejos que tardan en ejecutarse.

He pasado tiempo buscando en Google para encontrar una solución, pero hasta ahora sin suerte,

Gracias por su ayuda

+1

proceso de configuración del demonio, que está sondeando cada X segundos SHOW PROCESSLIST' de MySQL y mata a todas las consultas que tienen más de Y segundos – rabudde

+0

sí que vi a este enfoque similar utilizando PHP que se lleva todos los procesos en ejecución y la ejecución veces y luego puede matarlos con un comando mysql. Una idea ingeniosa, muy sorprendente, no hay algo nativo que proteja contra esto. Parece extraño que mysql permita que los procesos funcionen esencialmente para siempre y acapare todos los recursos del sistema en el proceso. – x9sim9

+0

La clase base DbCommand en .NET tiene una propiedad CommandTimeout que establece el tiempo de espera antes de finalizar el intento de ejecutar un comando y generar un error. – Devart

Respuesta

0

No hay manera de hacerlo utilizando las opciones de MySQL. Pero aún puede hacerlo usando el proceso de daemon como se recomienda @rabudde.

En este caso, si mata el proceso, cancelará la transacción y se revertirá.

+1

¡Tenga en cuenta que las transacciones inversas también pueden generar una carga significativa en el servidor! Desafortunadamente, esto difícilmente puede predecirse, pero como regla general, debe saber que si una transacción se ha estado ejecutando durante un tiempo y tocará muchos registros, su tiempo de reversión aumentará. Esto empeora cuando hay varias transacciones interactuando (incluye SELECCIONAR) con las mismas filas. –

+0

Afortunadamente, puedo obtener la consulta que se está ejecutando, por lo que se pondrá algo en su lugar para permitir que las consultas que no sean SELECT respiren más espacio. Hasta el momento, TBH no tenía problemas con el rendimiento relacionado con INSERT/UPDATE/REPLACE; hasta ahora, las consultas SELECT generalmente se hacían con mysql eligiendo los índices incorrectos y, sorprendentemente, FORCE INDEX (principal) arreglando aproximadamente el 90% de estas consultas. – x9sim9

3

Esta es una solución puramente php que parece ser la solución más simple de la que he logrado encontrar hasta ahora.

$result = mysql_query("SHOW FULL PROCESSLIST"); 
while ($row=mysql_fetch_array($result)) 
{ 
    $process_id = $row["Id"]; 
    if ($row["Time"] > 200) 
    { 
    $sql="KILL {$process_id}"; 
    mysql_query($sql); 
    } 
} 

Y ejecuta esto desde un script CRON cada 60 segundos.

Si alguien lo hace encontrar una mejor solución a este problema por favor hágamelo saber

3

puede usar el siguiente procedimiento para verificar si las consultas tienen una duración superior a 300 segundos. el evento ejecuta el procedimiento periódicamente y elimina todas las consultas de larga ejecución.

CREATE PROCEDURE DBNAME.kill_long_running_queries() 
BEGIN 

    DECLARE v_qid BIGINT; 
    DECLARE v_finished INT DEFAULT 0; 
    DECLARE c_queries CURSOR FOR SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND = 'Query' AND TIME > 300; 
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1; 

    OPEN c_queries; 

    l_fetch_queries: LOOP 
    FETCH c_queries INTO v_qid; 
    IF v_qid > 0 THEN 
     KILL QUERY v_qid; 
    END IF; 
    IF v_finished THEN 
     LEAVE l_fetch_queries; 
    END IF; 
    END LOOP l_fetch_queries; 
    CLOSE c_queries; 

END 

CREATE EVENT kill_long_running_queries 
ON SCHEDULE EVERY 60 SECOND 
DO CALL DBNAME.kill_long_running_queries(); 
+0

¡Esto funciona genial, gracias! Nunca antes había oído hablar de eventos MySQL, necesitaba agregar la línea 'event_scheduler = 1' en _my.cnf_ para habilitarlos. –

Cuestiones relacionadas