Глобальный тайм-аут запроса в MySQL 5.6 - PullRequest
0 голосов
/ 02 января 2019

Мне нужно применить тайм-аут запроса на глобальном уровне в моем приложении.Запрос: SET SESSION max_execution_time=1 делает это с MySQL 5.7.Я использую MySQL 5.6 и не могу обновить в данный момент.Любое решение с использованием SQL Alchemy также поможет.

1 Ответ

0 голосов
/ 02 января 2019

Похоже, в MySQL до версий 5.7.4 и 5.7.8 нет эквивалента - max_execution_time (параметр изменил свое имя).Что вы можете сделать, это создать свою собственную периодическую работу, которая проверяет, превысил ли время ожидания запросы, и вручную убивает их.К сожалению, это не совсем то же, что и в более новых версиях MySQL: без проверки информации о команде вы в конечном итоге убьете все запросы, а не просто прочитаете только SELECT, и практически невозможно управлять на уровне сеанса.

Один из способов сделать это - создать хранимую процедуру , которая запрашивает список процессов и убивает по мере необходимости.Такая хранимая процедура может выглядеть следующим образом:

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 ;

В качестве альтернативы вы можете реализовать все это в логике своего приложения, но для этого потребуется отдельное обратное обращение к базе данных для каждого запроса, подлежащего уничтожению.Остается периодически вызывать этот код:

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

Как и где именно сильно зависит от вашего фактического заявления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...