Mysql
 sql >> Database >  >> RDS >> Mysql

Timeout della query globale in MySQL 5.6

Sembra che non ci siano equivalenti a max_execution_time in MySQL prima delle versioni 5.7.4 e 5.7.8 (l'impostazione ha cambiato nome). Quello che puoi fare è creare il tuo lavoro periodico che controlla se le query hanno superato il timeout e le elimina manualmente. Sfortunatamente non è proprio la stessa cosa che fanno le versioni più recenti di MySQL:senza ispezionare le informazioni sul comando finirai per uccidere tutte le query, non solo leggere SELECT , ed è quasi impossibile da controllare a livello di sessione.

Un modo per farlo sarebbe creare una procedura memorizzata che interroga l'elenco di processi e uccisioni come richiesto. Tale procedura memorizzata potrebbe essere simile a:

DELIMITER //
CREATE PROCEDURE stmt_timeout_killer (timeout INT)
BEGIN
    DECLARE query_id INT;
    DECLARE done INT DEFAULT FALSE;

    DECLARE curs CURSOR FOR
    SELECT id
    FROM information_schema.processlist
    WHERE command = 'Query' AND time >= timeout;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    -- Ignore ER_NO_SUCH_THREAD, in case the query finished between
    -- checking the process list and actually killing threads
    DECLARE CONTINUE HANDLER FOR 1094 BEGIN END;

    OPEN curs;

    read_loop: LOOP
        FETCH curs INTO query_id;

        IF done THEN
            LEAVE read_loop;
        END IF;

        -- Prevent suicide
        IF query_id != CONNECTION_ID() THEN
            KILL QUERY query_id;
        END IF;
    END LOOP;

    CLOSE curs;
END//
DELIMITER ;

In alternativa, è possibile implementare tutto ciò nella logica dell'applicazione, ma richiederebbe round trip separati al database per l'uccisione di ogni query. Non resta quindi che chiamarlo periodicamente:

# Somewhere suitable
engine.execute(text("CALL stmt_timeout_killer(:timeout)"), timeout=30)

Come e dove esattamente dipende molto dalla tua applicazione effettiva.