2

MySQL サーバーを毎分チェックし、150 秒以上実行されたクエリを強制終了したいと考えています。私がこれをしたい主な理由は、特定の人々からのクエリが他のすべての人のためにDBをロックしたくないからです. これが問題の究極の解決策ではないことはわかっていますが、少なくともクエリで問題が発生した場合のフォールバックです。スレーブ DB はありません (これは単なる在宅プロジェクトです)。

これを実行するスクリプトをスケジュールして実行したいと思います。Perl や Ruby に慣れていないので、Windows 2008 Server ボックスで実行する必要があります。簡単なコマンド ライン スクリプトの作成を検討しましたが、それは不可能のようです。現在、次のようなことができることはわかっていますが、手動で行う必要があります。

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 までの 9 つのフィールドを取得できます。

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

各整数をチェックするIfステートメントがある理由は、プロセスのID番号との完全な一致を保証するためです。これらの9つのオプション以外は失敗し、プロセスリストに何含まれるかわからないため、申し訳ありませんが安全です。

于 2012-09-30T22:26:47.547 に答える