Wygląda na to, że nie ma odpowiednika
do max_execution_time
w MySQL przed wersjami 5.7.4 i 5.7.8 (ustawienie zmieniło nazwę). To, co możesz zrobić, to utworzyć własne okresowe zadanie, które sprawdza, czy zapytania przekroczyły limit czasu, i ręcznie je zabija. Niestety nie jest to dokładnie to samo, co nowsze wersje MySQL:bez sprawdzenia informacji o poleceniu zabijesz wszystkie zapytania, a nie tylko odczyt SELECT
, a kontrola na poziomie sesji jest prawie niemożliwa.
Jednym ze sposobów na to byłoby utworzenie procedury składowanej który wysyła zapytanie do listy procesów i zabija jako wymagane. Taka procedura składowana może wyglądać tak:
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 ;
Alternatywnie możesz zaimplementować to wszystko w logice aplikacji, ale wymagałoby to oddzielnych podróży w obie strony do bazy danych, aby każde zapytanie zostało zabite. Pozostaje więc okresowe wywoływanie tego:
# Somewhere suitable
engine.execute(text("CALL stmt_timeout_killer(:timeout)"), timeout=30)
Jak i gdzie dokładnie zależy w dużej mierze od Twojej aktualnej aplikacji.