Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Globales Abfrage-Timeout in MySQL 5.6

Es scheint kein Äquivalent zu geben zu max_execution_time in MySQL vor den Versionen 5.7.4 und 5.7.8 (die Einstellung hat ihren Namen geändert). Was Sie tun können, ist, Ihren eigenen regelmäßigen Job zu erstellen, der überprüft, ob Abfragen das Zeitlimit überschritten haben, und sie manuell beenden. Leider ist das nicht ganz dasselbe wie das, was die neueren MySQL-Versionen tun:Ohne die Befehlsinformationen zu überprüfen, werden Sie am Ende alle Abfragen beenden, nicht nur SELECT lesen , und es ist nahezu unmöglich, sie auf Sitzungsebene zu kontrollieren.

Eine Möglichkeit wäre, eine gespeicherte Prozedur die die Prozessliste abfragt und Kills nach Bedarf. Eine solche gespeicherte Prozedur könnte wie folgt aussehen:

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 ;

Alternativ könnten Sie all dies in Ihrer Anwendungslogik implementieren, aber es würde separate Roundtrips zur Datenbank für jede abzubrechende Abfrage erfordern. Was dann übrig bleibt, ist, dies regelmäßig aufzurufen:

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

Wie und wo genau, hängt stark von Ihrer konkreten Anwendung ab.