【问题标题】:How can I stop a MySQL query if it takes too long?如果需要太长时间,如何停止 MySQL 查询?
【发布时间】:2011-01-09 08:58:56
【问题描述】:

是否可以在 MySQL 中使查询超时?

也就是说,如果任何查询超过了我指定的时间,它就会被 MySQL 杀死,它会返回错误而不是等待永恒。

【问题讨论】:

  • 帮助我们回答这个问题 - 您是在代码内部还是外部尝试这样做?如果您想要特定语言的答案,选择哪一种?
  • 我不知道任何ANSI SQL,但我知道如何在一些消费应用程序中做到这一点——它们是如何连接的?每个连接都有 join-limit 语法,您可以在应用程序中执行很多操作。
  • 对不起,我很愚蠢,我忘了具体说明。我不想在我的代码中执行此操作,我想知道,是否可以在 mysql self 中执行此查询超时,例如:查询运行 120 秒,限制为 120,因此 mysql 将终止此查询并返回一些错误或者其他的东西。我遇到了令人讨厌的 3rd 方代码问题,我无权编辑它。我需要在 mysql 中终止该查询,而不是在代码中。

标签: mysql timeout


【解决方案1】:

MySQL 论坛有一些关于此的主题。

This post 详细介绍了如何使用 innodb_lock_wait_timeout 在服务器上设置超时。

Here's a way to do it programmatically,假设您使用的是 JDBC。

【讨论】:

    【解决方案2】:

    从 MySQL 5.1 开始,您可以创建一个存储过程来查询 information_schmea.PROCESSLIST 表中所有符合“长时间运行”条件的查询,然后遍历游标以终止它们。然后设置该过程以在事件调度程序中重复执行。

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

    【讨论】:

    【解决方案3】:

    我刚刚将以下 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
    

    【讨论】:

      【解决方案4】:

      这是我的脚本:

      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
      

      【讨论】:

        【解决方案5】:

        我认为上面的 egrep 不会找到“2000”。
        为什么不尝试只选择 id 并避免所有那些豪华的 shell 东西:

        mysql -e 'select id from information_schema.processlist where info is not null and time > 30;'
        

        【讨论】:

          【解决方案6】:

          在 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 工具,否则您需要在命令行上提供凭据。

          【讨论】:

          【解决方案7】:

          我以为它已经存在了一段时间,但根据this

          MySQL 5.7.4 引入了为顶级只读 SELECT 语句设置服务器端执行时间限制的功能,以毫秒为单位。

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

          请注意,这只适用于只读 SELECT 语句。

          【讨论】:

          • NB:在 v 5.7.8 中重命名为 MAX_EXECUTION_TIME
          【解决方案8】:

          从 MySQL 5.7.8 开始,max_execution_time 选项定义了 SELECT 语句的执行超时。

          【讨论】:

            【解决方案9】:

            我认为这个老问题需要更新的答案。

            您可以为所有只读SELECT 查询设置GLOBAL 超时,如下所示:

            SET GLOBAL MAX_EXECUTION_TIME=1000;

            指定的时间以毫秒为单位。

            如果您只希望特定查询的超时,您可以像这样将其设置为内联:

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

            MySQL 返回一个错误而不是等待永恒。

            请注意,此方法仅适用于只读SELECTs。如果确定SELECT 语句不是只读的,则取消为其设置的任何计时器并向用户报告以下 NOTE 消息:

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

            对于带有子查询的语句,它只限制顶部的SELECT。它不适用于存储程序中的SELECT 语句。在存储程序中的 SELECT 语句中使用 MAX_EXECUTION_TIME 提示将被忽略。

            【讨论】:

            • 这是在 Windows 上运行的 MySql 5.7.21 中工作的那个。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-07-28
            • 1970-01-01
            • 2015-05-17
            • 1970-01-01
            • 1970-01-01
            • 2020-11-12
            相关资源
            最近更新 更多