Как я могу остановить MySQL запрос, если он занимает слишком много времени? - PullRequest
44 голосов
/ 26 января 2010

Возможно ли тайм-аут запроса в MySQL?

То есть, если какой-либо запрос превысит указанное мной время, он будет уничтожен MySQL и вернет ошибку вместо ожидания вечности.1003 *

Ответы [ 9 ]

10 голосов
/ 21 сентября 2012

На CPAN есть хороший Perl-скрипт, который делает именно это: http://search.cpan.org/~rsoliv/mysql-genocide-0.03/mysql-genocide

Нужно только запланировать его запуск с правильными параметрами. Создайте файл CRONtab / etc / cron.d / mysql_query_timeout , чтобы запланировать его запуск каждую минуту:

* * * * * root /path/to/mysql-genocide -t 7200 -s -K

Где 7200 - максимально допустимое время выполнения в секундах. Ключ -s отфильтровывает все, кроме запросов SELECT. Ключ -K указывает сценарию завершить соответствующие процессы.

Пользователь root должен иметь возможность запускать локальные инструменты mysql без аутентификации, в противном случае вам потребуется предоставить учетные данные в командной строке.

9 голосов
/ 04 августа 2011

Я просто настроил следующий скрипт bash как задание cron для выполнения этого с MySQL 5.0 (убивает любой запрос, который выполнялся более 30 секунд). Делитесь им здесь, если это окажется полезным для всех (извините, если мой стиль сценариев bash неэффективен или зверен, это не мой основной язык разработки):

#!/bin/bash
linecount=0
processes=$(echo "show processlist" | mysql -uroot -ppassword)
oldIfs=$IFS
IFS='
'
echo "Checking for slow MySQL queries..."
for line in $processes
do
    if [ "$linecount" -gt 0 ]
        then
            pid=$(echo "$line" | cut -f1)
            length=$(echo "$line" | cut -f6)
            query=$(echo "$line" | cut -f8)
            #Id User    Host    db  Command Time    State   Info
            if [ "$length" -gt 30 ]
                then
                    #echo "$pid = $length"
                    echo "WARNING:  Killing query with pid=$pid with total execution time of $length seconds! (query=$query)"
                    killoutput=$(echo "kill query $pid" | mysql -uroot -ppassword)
                    echo "Result of killing $pid:  $killoutput"
            fi
    fi
    linecount=`expr $linecount + 1`
done
IFS=$oldIfs
8 голосов
/ 27 апреля 2014

Я думал, что это было немного дольше, но согласно это ,

MySQL 5.7.4 предоставляет возможность устанавливать ограничения времени выполнения на стороне сервера, указанные в миллисекундах, для операторов SELECT только для чтения верхнего уровня.

SELECT 
MAX_STATEMENT_TIME = 1000 --in milliseconds
* 
FROM table;

Обратите внимание, что это работает только для операторов SELECT только для чтения.

8 голосов
/ 03 ноября 2010

Начиная с MySQL 5.1, вы можете создать хранимую процедуру для запроса таблицы information_schmea.PROCESSLIST ко всем запросам, которые соответствуют вашим критериям для "длительного запуска", а затем выполнить итерацию курсора, чтобы убить их. Затем настройте эту процедуру для регулярного выполнения в планировщике событий.

См .: http://forge.mysql.com/tools/tool.php?id=106

7 голосов
/ 26 января 2010

На форуме MySQL есть несколько тем по этому поводу.

В этом посте подробно описано, как настроить тайм-ауты на сервере с помощью innodb_lock_wait_timeout.

Вот способ сделать это программно , при условии, что вы используете JDBC.

3 голосов
/ 29 августа 2017

Я думаю, что этот старый вопрос нуждается в обновленном ответе.

Вы можете установить GLOBAL тайм-аут для всех ваших запросов только для чтения SELECT, например:

SET GLOBAL MAX_EXECUTION_TIME=1000;

Время указано в миллисекундах.

Если вы хотите тайм-аут только для определенного запроса, вы можете установить его в строке следующим образом:

SELECT /*+ MAX_EXECUTION_TIME(1000) */ my_column FROM my_table WHERE ...

MySQL возвращает ошибку вместо ожидания вечности.

Обратите внимание, что этот метод работает только для чтения SELECT s. Если определено, что оператор SELECT не предназначен только для чтения, то любой таймер, установленный для него, отменяется, и пользователю сообщается следующее сообщение ПРИМЕЧАНИЕ:

Note 1908 Select is not a read only statement, disabling timer

Для операторов с подзапросами ограничивает только верхнюю SELECT. Это не относится к SELECT операторам в хранимых программах. Использование подсказки MAX_EXECUTION_TIME в операторах SELECT в хранимой программе будет игнорироваться.

3 голосов
/ 12 июня 2012

Я не думаю, что egrep выше найдет "2000".
Почему бы не попробовать просто выбрать идентификатор и избежать всего этого шикарного содержимого оболочки:

mysql -e 'select id from information_schema.processlist where info is not null and time > 30;'
2 голосов
/ 08 декабря 2016

Начиная с MySQL 5.7.8, существует опция max_execution_time , определяющая время ожидания выполнения для операторов SELECT.

2 голосов
/ 29 ноября 2011

Вот мой сценарий:

mysql -e 'show processlist\G' |\
egrep -b5 'Time: [6-9]{3,10}' |\
grep 'Id:' |\
cut -d':' -f2 |\
grep -v '155' |\ ## Binary Log PID
sed 's/^ //' |\
while read id
do
    mysql -e "kill $id;"
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...