2

我想每分钟检查一次我的 MySQL 服务器并终止运行时间超过 150 秒的查询。我想这样做的主要原因是因为我不希望某些人的查询为其他人锁定数据库。我知道这不是问题的最终解决方案,但至少它是一个备用方案,以防查询出现问题。我没有从属数据库(这只是一个家庭项目)。

我想安排一个脚本来为我执行此操作。我不熟悉 Perl 或 Ruby,我需要在我的 Windows 2008 Server 机器上完成它。我已经研究过创建一个简单的 cmd 行脚本,但这似乎是不可能的。我知道目前我可以做这样的事情,但我必须手动做:

mysqladmin processlist
mysqladmin kill

有人对我如何做到这一点有任何想法或例子吗?

4

2 回答 2

1

如果你安装了 Wscript - 我认为应该是 - 你可以试试这个。另存为“somethingorother.vbs”并不时执行。或者您可以使用提供的循环。loop 和 kill-for-real 选项都有注释;在生产服务器上取消注释之前测试脚本。

我假设 'mysqladmin processlist' 输出类似这样的内容(取自我的 XP):

+----+------+----------------+----+---------+------+-------+------------------+
| Id | User | Host           | db | Command | Time | State | Info             |
+----+------+----------------+----+---------+------+-------+------------------+
| 21 | root | localhost:1648 |    | Query   | 0    |       | show processlist |
+----+------+----------------+----+---------+------+-------+------------------+

所以我们要去掉包含“----”的行和包含“Id | User”的行,剩下的就是

| 21 | root | localhost:1648 |    | Query   | 0    |       | show processlist |

我们可以用管道符号“|”分割,得到从 0 到 8 的九个字段:

0   1     2          3          4      5        6      7           8
 | 21 | root | localhost:1648 |    | Query   | 0    |       | show processlist |

字段 #1 是 Id,字段 #6 产生运行时间。

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
于 2012-09-30T20:49:00.730 回答
0

这是我最终使用的最终脚本。感谢 Iserni 的初步回答,帮助我达到了这一点!

我最终从调用 csript.exe 的 .bat 文件启动它,因为我可以将消息输出到命令行控制台(而不是消息框)。如果要输出到文本文件,也可以添加它,只需确保启动具有完全管理员 UAC 访问权限的 .bat 文件即可。以下是 .bat 文件包含的内容:

C:\Windows\System32\cscript.exe "C:\Program Files\MySQL\MySQL Server 5.6\bin\kill-slow-queries.vbs"

这是 .vbs 文件中的内容:

    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

我有一个检查每个 Integer 的 If 语句的原因是因为它保证并完全匹配进程的 ID 号。除了这九个选项之外的任何选项都会失败,而且您永远不知道进程列表中可能包含什么,所以安全总比抱歉好。

于 2012-09-30T22:26:47.547 回答