mysqld-watcher.pl 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #!/usr/bin/env perl -w
  2. #
  3. # The contents of this file are subject to the Mozilla Public
  4. # License Version 1.1 (the "License"); you may not use this file
  5. # except in compliance with the License. You may obtain a copy of
  6. # the License at http://www.mozilla.org/MPL/
  7. #
  8. # Software distributed under the License is distributed on an "AS
  9. # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10. # implied. See the License for the specific language governing
  11. # rights and limitations under the License.
  12. #
  13. # The Original Code is the Bugzilla Bug Tracking System.
  14. #
  15. # The Initial Developer of the Original Code is Netscape Communications
  16. # Corporation. Portions created by Netscape are
  17. # Copyright (C) 2000 Netscape Communications Corporation. All
  18. # Rights Reserved.
  19. #
  20. # Contributor(s): Dan Mosedale <dmose@mozilla.org>
  21. #
  22. # mysqld-watcher.pl - a script that watches the running instance of
  23. # mysqld and kills off any long-running SELECTs against the shadow_db
  24. #
  25. use strict;
  26. # some configurables:
  27. # length of time before a thread is eligible to be killed, in seconds
  28. #
  29. my $long_query_time = 180;
  30. #
  31. # the From header for any messages sent out
  32. #
  33. my $mail_from = "root\@mothra.mozilla.org";
  34. #
  35. # the To header for any messages sent out
  36. #
  37. my $mail_to = "root";
  38. #
  39. # mail transfer agent. this should probably really be converted to a Param().
  40. #
  41. my $mta_program = "/usr/lib/sendmail -t -ODeliveryMode=deferred";
  42. # The array of long-running queries
  43. #
  44. my $long = {};
  45. # Run mysqladmin processlist twice, the first time getting complete queries
  46. # and the second time getting just abbreviated queries. We want complete
  47. # queries so we know which queries are taking too long to run, but complete
  48. # queries with line breaks get missed by this script, so we get abbreviated
  49. # queries as well to make sure we don't miss any.
  50. foreach my $command ("/opt/mysql/bin/mysqladmin --verbose processlist",
  51. "/opt/mysql/bin/mysqladmin processlist")
  52. {
  53. close(STDIN);
  54. open(STDIN, "$command |");
  55. # iterate through the running threads
  56. #
  57. while ( <STDIN> ) {
  58. my @F = split(/\|/);
  59. # if this line is not the correct number of fields, or if the thread-id
  60. # field contains Id, skip this line. both these cases indicate that this
  61. # line contains pretty-printing gunk and not thread info.
  62. #
  63. next if ( $#F != 9 || $F[1] =~ /Id/);
  64. if ( $F[4] =~ /shadow_bugs/ # shadowbugs database in use
  65. && $F[5] =~ /Query/ # this is actually a query
  66. && $F[6] > $long_query_time # this query has taken too long
  67. && $F[8] =~ /(select|SELECT)/ # only kill a select
  68. && !defined($long->{$F[1]}) ) # haven't seen this one already
  69. {
  70. $long->{$F[1]} = \@F;
  71. system("/opt/mysql/bin/mysqladmin", "kill", $F[1]);
  72. }
  73. }
  74. }
  75. # send an email message
  76. #
  77. # should perhaps be moved to somewhere more global for use in bugzilla as a
  78. # whole; should also do more error-checking
  79. #
  80. sub sendEmail($$$$) {
  81. ($#_ == 3) || die("sendEmail: invalid number of arguments");
  82. my ($from, $to, $subject, $body) = @_;
  83. open(MTA, "|$mta_program");
  84. print MTA "From: $from\n";
  85. print MTA "To: $to\n";
  86. print MTA "Subject: $subject\n";
  87. print MTA "\n";
  88. print MTA $body;
  89. print MTA "\n";
  90. close(MTA);
  91. }
  92. # if we found anything, kill the database thread and send mail about it
  93. #
  94. if (scalar(keys(%$long))) {
  95. my $message = "";
  96. foreach my $process_id (keys(%$long)) {
  97. my $qry = $long->{$process_id};
  98. $message .= join(" ", @$qry) . "\n\n";
  99. }
  100. # fire off an email telling the maintainer that we had to kill some threads
  101. #
  102. sendEmail($mail_from, $mail_to, "long running MySQL thread(s) killed", $message);
  103. }