• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer navigation

The Geek Diary

  • OS
    • Linux
    • CentOS/RHEL
    • Solaris
    • Oracle Linux
    • VCS
  • Interview Questions
  • Database
    • oracle
    • oracle 12c
    • ASM
    • mysql
    • MariaDB
  • DevOps
    • Docker
    • Shell Scripting
  • Big Data
    • Hadoop
    • Cloudera
    • Hortonworks HDP

MySQL: How to kill a Long Running Query using max_execution_time

by admin

In this post, we will learn about what options are available if you need to automatically kill long-running queries.

MySQL 5.7 and Later For SELECT Statement

Starting from MySQL 5.7.4 there is support for automatic timeouts of read-only SELECT statements (the following discussion assumes 5.7.8 or later as the feature had changes to the option/hint name and syntax).

There are two ways to set an upper limit of how long a read-only SELECT statement is allowed to execute:

  • the max_execution_time option
  • the MAX_EXECUTION_TIME() optimizer hint for SELECT statements

The following applies:

  • Only read-only SELECT statements are affected.
  • Only the top level (i.e. not subqueries) are affected.
  • SELECT statements inside stored programs are not affected (the MAX_EXECUTION_TIME() hint is not supported in stored programs).

These two options will be discussed in the following.

The max_statement_time Option

The max_execution_time option specifies the timeout for read-only SELECT statements if the MAX_EXECUTION_TIME() optimizer hint is not added. The value is in milliseconds.

The option exists both at the GLOBAL and SESSION level and can be changed dynamically. The GLOBAL value is used as the default for the SESSION value. A value of 0 means that no timeout is in effect.

mysql> connect
Connection id:    5
Current database: *** NONE ***

mysql> SELECT @@global.max_statement_time, @@session.max_statement_time;
+-----------------------------+------------------------------+
| @@global.max_statement_time | @@session.max_statement_time |
+-----------------------------+------------------------------+
|                        1000 |                         1000 |
+-----------------------------+------------------------------+
1 row in set (0.00 sec)
mysql> SET SESSION max_statement_time = 2000; -- 2 seconds
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@global.max_statement_time, @@session.max_statement_time;
+-----------------------------+------------------------------+
| @@global.max_statement_time | @@session.max_statement_time |
+-----------------------------+------------------------------+
|                        1000 |                         2000 |
+-----------------------------+------------------------------+
1 row in set (0.00 sec)

A query taking 1.5 seconds succeeds:

mysql> SELECT SLEEP(1.5);
+------------+
| SLEEP(1.5) |
+------------+
|          0 |
+------------+
1 row in set (1.51 sec)

A query taking more than 2 seconds fails:

mysql> SELECT SLEEP(5);
+----------+
| SLEEP(5) |
+----------+
|        1 |
+----------+
1 row in set (2.02 sec)

Only SELECT statements are affected:

mysql> DO SLEEP(5);
Query OK, 0 rows affected (5.00 sec)

The MAX_STATEMENT_TIME Clause for SELECT Statements

The MAX_EXECUTION_TIME() optimize hint can be used to change the timeout for a specific query. For example if max_execution_time is set to 1 second, but you know a given query takes 5 seconds, then you can change the timeout:

mysql> SELECT @@global.max_execution_time, @@session.max_execution_time;
+-----------------------------+------------------------------+
| @@global.max_execution_time | @@session.max_execution_time |
+-----------------------------+------------------------------+
|                        1000 |                         1000 |
+-----------------------------+------------------------------+
1 row in set (0.00 sec)
mysql> SELECT /*+ MAX_EXECUTION_TIME(6000) */ /* may take up to 5+ seconds - don't kill */ SLEEP(5);
+----------+
| SLEEP(5) |
+----------+
|        0 |
+----------+
1 row in set (5.00 sec)

or you can use it to lower the timeout:

mysql> SELECT /*+ MAX_EXECUTION_TIME(500) */ /* may take up to 5+ seconds - don't kill */ SLEEP(5);
+----------+
| SLEEP(5) |
+----------+
|        1 |
+----------+
1 row in set (0.50 sec

All Versions and All Statement Types

Important: If you are changing data in non-transactional tables, such as MyISAM tables, killing the query will not roll back the transaction. This means your data will be in an unknown state where the effects of the statement is partly applied. If you use replication, you will need to rebuild the replicas. In general, for non-transactional engines, it is better to leave the statement running.

Before MySQL 5.7.4 there is no built-in way to automatically kill long running queries. Instead, one of the two following solutions can be used:

  • Write a script that periodically checks whether there are any long running queries and kills them if needed.
  • Write a stored procedure that can be executed using the event scheduler. This option is only available in MySQL 5.1 and later as earlier versions did not have support for events.

Both works in very similar ways. The first has the advantage that you can choose the programming language of your choice whereas the stored procedure/event solution keeps everything inside the database.

Note: InnoDB transactions that have modified a large number of rows will take a while to roll back. As a rule of thumb, you should expect the rollback to take 10 times as long as making the modifications. So you want to consider the number of undo entries for a transaction before killing it.

To implement the check you will need to use the process list. In MySQL 5.1 and later, you can use the information_schema.PROCESSLIST table which makes it possible to get the process list from a standard SELECT query which is necessary if the solution is implemented inside a stored procedure. In MySQL 5.6 and later the performance_schema.threads table can be used (and is in general preferred as it requires fewer locks than SHOW PROCESSLIST or information_schema.PROCESSLIST).

For InnoDB, you may be interested in long running transactions even as well. These can be monitored through the INNODB_TRX in the Information Schema. The INNODB_TRX table includes when the transaction was started.

You may also want to take into consideration whether any other queries are waiting for locks held by the long running query. For InnoDB tables, this can easily be checked using the INNODB_LOCK_WAITS and INNODB_TRX tables in the Information Schema. The InnoDB Information Schema tables are available starting from MySQL 5.1 with the InnoDB Plugin and MySQL 5.5 and later.

While it is in general not good to have long-running queries and transactions as they may block other connections and increase the usage of resources, some queries will inevitably take a long time, for example, table rebuilds of large tables, bulk imports, etc. So you may want to consider a way to flag queries that you do not want to terminate; this could for example be through a comment at the beginning of the query.

Note: Make sure you test your solution. The above references are just examples and are meant as suggestions how to get started and are should not be considered production-ready solutions.

Filed Under: mysql

Some more articles you might also be interested in …

  1. MySQL Table Maintenance – InnoDB, MyISAM, MEMORY, ARCHIVE
  2. What are the various types of locking used in the MySQL Server
  3. How to Restore a Specific Database or Table (MySQL)
  4. How to find Which Process Is Killing mysqld With SIGKILL or SIGTERM on Linux
  5. MySQL Server Error – “Can’t Create A New Thread (errno 11)”
  6. How to use mysqldump without CREATE TABLE statements
  7. Understanding MySQL Pluggable Authentication
  8. What’s a good process to find and eliminate slow queries in MySQL
  9. Beginners Guide to Management of MySQL Cluster Log Files
  10. Examples of mysqldump partial backups

You May Also Like

Primary Sidebar

Recent Posts

  • fprintd-delete Command Examples in Linux
  • fprintd-delete: command not found
  • foreman: command not found
  • foreman Command Examples in Linux

© 2023 · The Geek Diary

  • Archives
  • Contact Us
  • Copyright