I want to check my MySQL server every minute and kill queries that have run longer than 150 seconds. The main reason I want to do this is because I don't want queries from certain people to lock up the DB for everyone else. I know this is not the ultimate solution to the problem, but at least it's a fallback in case something goes wrong with a query. I don't have a slave DB (this is just an at-home project).
I'd like to schedule a script to run that does this for me. I'm unfamiliar with Perl or Ruby and I need it done on my Windows 2008 Server box. I've looked into creating a simple cmd line script, but that doesn't seem to be possible. I know currently I can do something like this but I have to do it manually:
mysqladmin processlist
mysqladmin kill
Anyone have any ideas or examples on how I could do this?
If you have Wscript installed - I think it should be - you can try this. Save as "somethingorother.vbs" and execute every now and then. Or you can use the provided loop. Both loop and kill-for-real options are commented; test the script before uncommenting on a production server.
I assume that 'mysqladmin processlist' outputs something like this (taken from my XP):
+----+------+----------------+----+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+----------------+----+---------+------+-------+------------------+
| 21 | root | localhost:1648 | | Query | 0 | | show processlist |
+----+------+----------------+----+---------+------+-------+------------------+
So we have to eliminate rows containing "----" and rows containing "Id | User", and what remains is
| 21 | root | localhost:1648 | | Query | 0 | | show processlist |
which we can split by pipe signs '|', getting nine fields from 0 to 8:
0 1 2 3 4 5 6 7 8
| 21 | root | localhost:1648 | | Query | 0 | | show processlist |
Field #1 is Id, and field #6 yields the run time.
Option Explicit
Dim objShell, objWshScriptExec, objStdOut, strLine
Dim id, fields, rt, Killer, KillRun
' While True
' WScript.Sleep 150000
Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec("mysqladmin processlist")
Set objStdOut = objWshScriptExec.StdOut
While Not objStdOut.AtEndOfStream
strLine = objStdOut.ReadLine
If (InStr(strLine, "----") = 0 and InStr(strLine, "| Id | User |") = 0) Then
fields = Split(strLine, "|")
id = trim(fields(1))
rt = trim(fields(6))
If rt > 150 Then
' Set Killer = CreateObject("WScript.Shell")
' Set KillRun = objShell.Exec("mysqladmin kill " & id)
echo
End If
End If
Wend
' Wend
Here is the final script I ended up using. Thanks to Iserni with his initial answer that helped me get to this point!
I ended up launching this from a .bat file where csript.exe is call because I can output messages to the command line console (rather than a message box). If you want to output to a text file, you can add that as well, just make sure you launch the .bat file with full Administrator UAC access. Here is what the .bat file contains:
C:\Windows\System32\cscript.exe "C:\Program Files\MySQL\MySQL Server 5.6\bin\kill-slow-queries.vbs"
And here is what is inside of the .vbs file:
Option Explicit
Dim objShell, objWshScriptExec, objStdOut, strLine, fields
Dim id, rt, Killer, KillRun
While True
WScript.Sleep 10000
Set objShell = CreateObject("WScript.Shell")
Set objWshScriptExec = objShell.Exec("C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqladmin processlist -u root -pMYPASSWORD")
Set objStdOut = objWshScriptExec.StdOut
On Error Resume Next
While Not objStdOut.AtEndOfStream
strLine = objStdOut.ReadLine
If InStr(strLine, "| 1") > 0 or InStr(strLine, "| 2") > 0 or InStr(strLine, "| 3") > 0 or InStr(strLine, "| 4") > 0 or InStr(strLine, "| 5") > 0 or InStr(strLine, "| 6") > 0 or InStr(strLine, "| 7") > 0 or InStr(strLine, "| 8") > 0 or InStr(strLine, "| 9") > 0 Then
fields = Split(strLine, "|")
id = trim(fields(1))
rt = trim(fields(6))
If rt = "" Then
rt = 0
End If
WScript.Echo "ID: " + id + " Time: " + rt
If rt > 80 Then
Set Killer = CreateObject("WScript.Shell")
Set KillRun = objShell.Exec("C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqladmin kill " + id + " -u root -pMYPASSWORD")
WScript.Echo "Killed ID: " + id
End If
End If
Wend
WScript.Echo ""
WScript.Echo ""
Wend
The reason I have an If statement that checks for each Integer is because it guarantees and exact match to an ID number of a process. Anything other than those nine options will fail, and you never know what the process list could contain there, so better safe than sorry.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.