Automatic kill/timeout slow queries in MySQL - mysql

Is there some configuration that can be done at MySQL side to automatically kill or timeout queries that are extremely slow, say 100 seconds.

You can list all your MySQL queries by the following command:
$ mysqladmin processlist
so you can run some script which will parse that list and it'll kill the specific query.
In example, you can run some script in any language via cron to periodically check for the long queries, e.g.:
$result = mysql_query("SHOW FULL PROCESSLIST");
while ($row=mysql_fetch_array($result)) {
$process_id=$row["Id"];
if ($row["Time"] > 200 ) {
$sql="KILL $process_id";
mysql_query($sql);
}
}
Another example:
mysql> select concat('KILL ',id,';') from information_schema.processlist
where user='root' and time > 200 into outfile '/tmp/a.txt';
mysql> source /tmp/a.txt;
Related:
How do I kill all the processes in Mysql "show processlist"?
Read more:
http://www.mysqlperformanceblog.com/

Starting with MySQL 5.1 you can create a stored procedure to query the information_schmea.PROCESSLIST table for all queries that match your criteria ("long running time" in your case). Upon querying processlist table, you can simply iterate over a cursor to kill the running query processes that exceeds your timeout criteria.
Take a look at the following example: Procedure to find and terminate all non-SUPER and "system account" queries running longer than N seconds
http://forge.mysql.com/tools/tool.php?id=106

You should checkout the command pt-kill of percona toolkit

Related

How to set timeout on MySql query?

I have a shell script how execute some query on a big loop, but sometimes the script doesn't respond.
I want to add a timeout to Mysql query to prevent this bug.
$sql=`mysql --protocol=tcp --user=**** --password=\'****\' --host="vl*****1" --database="C***K" -e "UPDATE C****k SET current_status =\'$status\',last_state_change=\'$lastchange\' WHERE MC_internal_name=\'$InternalName\';"
Tkanks !
Use option:
--connect-timeout=#
Replace dash with number of seconds before connection timeout.

Estimating MySQL Query Runtime

I ran a MySQL query from command line using the following:
nohup mysql --user=root --password=XXXXXXXXX database < report.sql > results.tab
This query is extensive (5000 lines) and running a complex search over 90,000,000 rows from 150 tables.
This query has been running for over 24 hours and has not yet finished.
Is there a way I can run status check on this running query?
try show processlist in mysql if that works.

How to close existing connection in MySQL

I found that some connection got unclosed after the execution of command from Mysql server.
How can I configure my Mysql server so that I can close them all after executing a command?
if you can get the process_id inside mysql you can kill the process. Killing any process should work (though it will create a new connection next time you send a command).
mysql> SHOW PROCESSLIST; -- or SHOW FULL PROCESSLIST
mysql> KILL process_number;
Configure the wait_timeout variable to something soon enough, for example 30 seconds

How to monitor and automatically restart mysql?

I'm running mysql on Debian.
Is there a way to monitor mysql and restart it automatically if it locks up? For example sometimes the server starts to take 100% of cpu and starts running very slowly. If I restart mysql, things clear up and the server starts working fine, but I'm not always present to restart it manually.
Is there a way to monitor mysql and if the cpu is above 95% for more than 10 minutes straight then then mysql will automatically be restarted
You can write a cronjob to use
show processlist;
show processlist will return column Time and Id,
you can add more logic to check,
like query stuck for more than 600 seconds and the query is SELECT,
you can use Id value to perform kill $id;
This is safer than blindly restarting your server.
And if you have segregate between read/write (meaning read only SQL will use user with read privileges only), this can even simpler.
Use this bash script to check every minute.
#!/bin/bash
#Checking whether MySQL is alive or not
if mysqladmin ping | grep "alive"; then
echo "MySQL is up"
else
sudo service mysql restart
fi
`

How can I stop a MySQL query if it takes too long?

Is it possible to timeout a query in MySQL?
That is, if any query exceeds the time I specify, it will be killed by MySQL and it will return an error instead of waiting for eternity.
There is a nice Perl script on CPAN to do just this:
http://search.cpan.org/~rsoliv/mysql-genocide-0.03/mysql-genocide
One only needs to schedule it to run with the proper parameters. Create a CRONtab file /etc/cron.d/mysql_query_timeout to schedule it to run every minute:
* * * * * root /path/to/mysql-genocide -t 7200 -s -K
Where 7200 is the maxiumum allowed execution time in seconds. The -s switch filters out all except SELECT queries. The -K switch instructs the script to kill the matching processes.
The root user should be able to run local mysql tools without authentication otherwise you will need to provide credentials on the command line.
I just set up the following bash script as a cron job to accomplish this with MySQL 5.0 (kills any query that has been executing for more than 30 seconds). Sharing it here in case it proves useful to anyone (apologies if my bash scripting style is inefficient or atrocious, it is not my primary development language):
#!/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
I thought it has been around a little longer, but according to this,
MySQL 5.7.4 introduces the ability to set server side execution time limits, specified in milliseconds, for top level read-only SELECT statements.
SELECT
MAX_STATEMENT_TIME = 1000 --in milliseconds
*
FROM table;
Note that this only works for read-only SELECT statements.
Starting with MySQL 5.1 you can create a stored procedure to query the information_schmea.PROCESSLIST table for all queries that match your criteria for "long running" then iterate over a cursor to kill them. Then setup that procedure to execute on a recurring basis in the event scheduler.
See: http://forge.mysql.com/tools/tool.php?id=106
The MySQL forum has some threads about this.
This post details how to set up timeouts on the server using innodb_lock_wait_timeout.
Here's a way to do it programmatically, assuming you're using JDBC.
I think this old question needs an updated answer.
You can set a GLOBAL timeout for all your read-only SELECT queries like this:
SET GLOBAL MAX_EXECUTION_TIME=1000;
The time specified is in milliseconds.
If you want the timeout only for a specific query, you can set it inline like this:
SELECT /*+ MAX_EXECUTION_TIME(1000) */ my_column FROM my_table WHERE ...
MySQL returns an error instead of waiting for eternity.
Note that this method only works for read-only SELECTs. If a SELECT statement is determined not to be read-only, then any timer set for it is cancelled and the following NOTE message is reported to the user:
Note 1908 Select is not a read only statement, disabling timer
For statements with subqueries, it limits the top SELECT only. It does not apply to SELECT statements within stored programs. Using the MAX_EXECUTION_TIME hint in SELECT statements within a stored program will be ignored.
I don't think the egrep above would find "2000".
Why not try just selecting the id as well, and avoiding all of that posh shell stuff:
mysql -e 'select id from information_schema.processlist where info is not null and time > 30;'
Since MySQL 5.7.8 there is max_execution_time option that defines the execution timeout for SELECT statements.
Here is my script :
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