~knielsen/ourdelta/bug_484127_484120_2

« back to all changes in this revision

Viewing changes to bakery/debian-5.1/additions/mysqlreport

  • Committer: Arjen Lentz
  • Date: 2009-10-28 03:20:03 UTC
  • mfrom: (54.4.30 ourdelta-mariadb51-2)
  • Revision ID: arjen@openquery.com-20091028032003-3ebv58q8zin6xxbd
Merge from 5.1 bakery branch
Made autobake-deb.sh from 5.1 branch into separate autobake51-deb.sh (nasty merge)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/perl -w
2
2
 
3
 
# mysqlreport v3.4a Jan 23 2008 
 
3
# mysqlreport v3.5 Apr 16 2008
4
4
# http://hackmysql.com/mysqlreport
5
5
 
6
6
# mysqlreport makes an easy-to-read report of important MySQL status values.
33
33
my %mycnf; # ~/.my.cnf
34
34
my ($tmpfile_fh, $tmpfile);
35
35
my ($stat_name, $stat_val, $stat_label);
36
 
my ($major, $minor, $patch, $x); # MySQL version
 
36
my $MySQL_version;
37
37
my (%stats, %vars); # SHOW STATUS, SHOW VARIABLES
38
38
my (%DMS_vals, %Com_vals, %ib_vals);
39
39
my ($dbh, $query);
92
92
$op{'com'} ||= 3;
93
93
$op{'c'}   ||= 1; # Used in collect_reports() if --r given integer value
94
94
 
 
95
$relative_live    = 0;
 
96
$relative_infiles = 0;
 
97
 
95
98
if(defined $op{'r'})
96
99
{
97
 
   if($op{r}) { $relative_live    = 1; }
 
100
   if($op{r}) { $relative_live    = 1; }  # if -r was given an integer value
98
101
   else       { $relative_infiles = 1; }
99
102
}
100
103
 
101
104
# The report is written to a tmp file first.
102
105
# Later it will be moved to $op{'outfile'} or emailed $op{'email'} if needed.
103
 
($tmpfile_fh, $tmpfile) = tempfile() or die("Cannot open temporary file for writing: $!\n");
 
106
($tmpfile_fh, $tmpfile) = tempfile() or die "Cannot open temporary file for writing: $!\n";
104
107
 
105
108
if($op{'detach'})
106
109
{
122
125
select $tmpfile_fh;
123
126
$| = 1 if ($op{'detach'} || $relative_live);
124
127
 
 
128
print "tmp file: $tmpfile\n" if $op{debug};
 
129
 
125
130
# Connect to MySQL
126
131
if(!$op{'infile'} && !$relative_infiles)
127
132
{
128
 
   my $dsn;
129
 
 
130
 
   if($mycnf{'socket'} && -S $mycnf{'socket'})
131
 
   {
132
 
      $dsn = "DBI:mysql:mysql_socket=$mycnf{socket}";
133
 
   }
134
 
   elsif($mycnf{'host'})
135
 
   {
136
 
      $dsn = "DBI:mysql:host=$mycnf{host}" . ($mycnf{port} ? ";port=$mycnf{port}" : "");
137
 
   }
138
 
   else
139
 
   {
140
 
      $dsn = "DBI:mysql:host=localhost";
141
 
   }
142
 
 
143
 
   if($op{debug})
144
 
   {
145
 
      print "DBI DSN: $dsn\n";
146
 
   }
147
 
 
148
 
   $dbh = DBI->connect($dsn, $mycnf{'user'}, $mycnf{'pass'}) or die;
 
133
   connect_to_MySQL();
149
134
}
150
135
 
151
136
$have_innodb_vals = 1; # This might be set to 0 later in get_MySQL_version()
192
177
sub show_help_and_exit
193
178
{
194
179
   print <<"HELP";
195
 
mysqlreport v3.4a Jan 23 2008
 
180
mysqlreport v3.5 Apr 16 2008
196
181
mysqlreport makes an easy-to-read report of important MySQL status values.
197
182
 
198
183
Command line options (abbreviations work):
224
209
 
225
210
sub get_user_mycnf
226
211
{
 
212
   print "get_user_mycnf\n" if $op{debug};
 
213
 
227
214
   return if $WIN;
228
215
   open MYCNF, "$ENV{HOME}/.my.cnf" or return;
229
216
   while(<MYCNF>)
238
225
   close MYCNF;
239
226
}
240
227
 
 
228
sub connect_to_MySQL
 
229
{
 
230
   print "connect_to_MySQL\n" if $op{debug};
 
231
 
 
232
   my $dsn;
 
233
 
 
234
   if($mycnf{'socket'} && -S $mycnf{'socket'})
 
235
   {
 
236
      $dsn = "DBI:mysql:mysql_socket=$mycnf{socket}";
 
237
   }
 
238
   elsif($mycnf{'host'})
 
239
   {
 
240
      $dsn = "DBI:mysql:host=$mycnf{host}" . ($mycnf{port} ? ";port=$mycnf{port}" : "");
 
241
   }
 
242
   else
 
243
   {
 
244
      $dsn = "DBI:mysql:host=localhost";
 
245
   }
 
246
 
 
247
   print "connect_to_MySQL: DBI DSN: $dsn\n" if $op{debug};
 
248
 
 
249
   $dbh = DBI->connect($dsn, $mycnf{'user'}, $mycnf{'pass'}) or die;
 
250
}
 
251
 
241
252
sub collect_reports
242
253
{
 
254
   print "collect_reports\n" if $op{debug};
 
255
 
243
256
   my $i;
244
257
 
245
258
   get_vals();
258
271
 
259
272
   for($i = 0; $i < $op{'c'}; $i++)
260
273
   {
 
274
      $dbh->disconnect();
 
275
 
261
276
      sleep($op{'r'});
262
277
 
 
278
      connect_to_MySQL();
 
279
 
263
280
      print "\n#\n# Interval report " , $i + 1 , ", +", sec_to_dhms(($i + 1) * $op{'r'}), "\n#\n";
264
281
 
265
282
      get_vals();
270
287
 
271
288
sub read_relative_infiles
272
289
{
 
290
   print "read_relative_infiles\n" if $op{debug};
 
291
 
273
292
   my $slurp;    # Used to check infiles for multiple sets of status values
274
293
   my $n_stats;  # Number of multiple sets of status values in an infile
275
294
   my $infile;
309
328
         for($i = 0; $i < $n_stats; $i++)
310
329
         {
311
330
            my ($fh, $name) = tempfile()
312
 
               or die("read_relative_infiles: cannot open temporary file for writing: $!\n");
 
331
               or die "read_relative_infiles: cannot open temporary file for writing: $!\n";
313
332
 
314
333
            push(@tmpfile_fh, $fh);
315
334
            push(@tmpfile_name, $name);
316
335
 
317
 
            print "read_relative_infiles: created tmp file '$name'\n" if $op{debug};
 
336
            print "read_relative_infiles: created tmp file '$name' for set $i\n" if $op{debug};
318
337
         }
319
338
 
320
339
         $i = 0;
322
341
 
323
342
         select $tmpfile_fh[$i];
324
343
 
325
 
         # Read infile again and copy each set of status values
326
 
         # to seperate tmp files
 
344
         # Read infile again and copy each set of status values to seperate tmp files
327
345
         open INFILE, "< $infile" or warn and next;
328
346
         while(<INFILE>)
329
347
         {
330
348
            next if /^\+/;
331
349
            next if /^$/;
332
350
 
333
 
            print;
 
351
            # The infile must begin with the system variable values.
 
352
            # Therefore, the first occurance of Aborted_clients indicates the beginning
 
353
            # of the first set of status values if no sets have occured yet ($stat_n == 0).
 
354
            # In this case, the following status values are printed to the current fh,
 
355
            # along with the system variable values read thus far, until Aborted_clients
 
356
            # occurs again. Then begins the second and subsequent sets of status values.
334
357
 
335
358
            if(/Aborted_clients/)
336
359
            {
337
 
               # The infile should begin with manually inserted system
338
 
               # var values (like key_buffer_size = 128M). Therefore,
339
 
               # the first occurance of /Aborted_clients/ indicates
340
 
               # the first set of status values only if no sets have
341
 
               # occured yet ($stat_n = 0). In this case, the following
342
 
               # status values are printed to the current fh along with
343
 
               # the system var values read so far until /Aborted_clients/
344
 
               # occurs again. Then begins the second and subsequent sets
345
 
               # of status values.
346
 
               next if $stat_n++ == 0;
347
 
 
 
360
               print and next if $stat_n++ == 0;
348
361
               select $tmpfile_fh[++$i];
349
362
            }
 
363
 
 
364
            print;
350
365
         }
351
366
         close INFILE;
352
367
 
357
372
         {
358
373
            close $tmpfile_fh[$i];
359
374
 
 
375
            print "read_relative_infiles: reading set $i tmp file '$tmpfile_name[$i]'\n"
 
376
               if $op{debug};
 
377
 
360
378
            read_infile($tmpfile_name[$i]);
361
379
            relative_infile_report($report_n++);
362
380
 
363
381
            if($WIN) { `del $tmpfile_name[$i]`;   }
364
382
            else     { `rm -f $tmpfile_name[$i]`; }
365
383
 
366
 
            print "read_relative_infiles: deleted tmp file '$tmpfile_name[$i]'\n"
 
384
            print "read_relative_infiles: deleted set $i tmp file '$tmpfile_name[$i]'\n"
367
385
               if $op{debug};
368
386
         }
369
387
 
373
391
 
374
392
sub relative_infile_report
375
393
{
 
394
   print "relative_infile_report\n" if $op{debug};
 
395
 
376
396
   my $report_n = shift;
377
397
 
378
398
   if($report_n == 1)
400
420
 
401
421
sub get_vals
402
422
{
 
423
   print "get_vals\n" if $op{debug};
 
424
 
403
425
   my @row;
404
426
 
405
427
   # Get status values
406
 
   if($major >= 5 && (($minor == 0 && $patch >= 2) || $minor > 0))
 
428
   if($MySQL_version >= 50002)
407
429
   {
408
430
      $query = $dbh->prepare("SHOW GLOBAL STATUS;");
409
431
   }
419
441
 
420
442
sub get_vars
421
443
{
 
444
   print "get_vars\n" if $op{debug};
 
445
 
422
446
   my @row;
423
447
 
424
448
   # Get server system variables
427
451
   while(@row = $query->fetchrow_array()) { $vars{$row[0]} = $row[1]; }
428
452
 
429
453
   # table_cache was renamed to table_open_cache in MySQL 5.1.3
430
 
   if($major >= 5 && (($minor == 1 && $patch >= 3) || $minor > 1))
 
454
   if($MySQL_version >= 50103)
431
455
   {
432
456
      $vars{'table_cache'} = $vars{'table_open_cache'};
433
457
   }
435
459
 
436
460
sub read_infile
437
461
{
 
462
   print "read_infile\n" if $op{debug};
 
463
 
438
464
   my $infile = shift;
439
465
 
440
 
   # Default values if not set in INFILE
 
466
   # Default required system variable values if not set in INFILE.
 
467
   # As of mysqlreport v3.5 the direct output from SHOW VARIABLES;
 
468
   # can be put into INFILE instead. See http://hackmysql.com/mysqlreportdoc
 
469
   # for details.
441
470
   $vars{'version'} = "0.0.0"         if !exists $vars{'version'};
442
471
   $vars{'table_cache'} = 64          if !exists $vars{'table_cache'};
443
472
   $vars{'max_connections'} = 100     if !exists $vars{'max_connections'};
450
479
   # One should also add:
451
480
   #    key_cache_block_size
452
481
   #    query_cache_size
453
 
   # to their infile if needed.
454
 
 
455
 
   open INFILE, "< $infile" or warn;
 
482
   # to INFILE if needed.
 
483
 
 
484
   open INFILE, "< $infile" or die "Cannot open INFILE '$infile': $!\n";
 
485
 
456
486
   while(<INFILE>)
457
487
   {
458
 
      next if /^\+\-/;
459
 
      next if /^$/;
460
 
 
461
 
      chomp;
462
 
 
463
 
      if(/([A-Za-z_]+)[\s\t|]+(\d+)/)
464
 
      {
465
 
         $stats{$1} = $2;
466
 
         next;
467
 
      }
468
 
 
469
 
      # Explicit var = val (e.g. key_buffer_size = 128M)
470
 
      if( /^\s*(\w+)\s*=\s*([0-9.]+)(M*)\s*$/ )
471
 
      {
472
 
         $vars{$1} = ($3 ? $2 * 1024 * 1024 : $2);
473
 
         print "read_infile: read '$_' as $1 = $vars{$1}\n" if $op{debug};
474
 
         next;
 
488
      last if !defined $_;
 
489
 
 
490
      next if /^\+/;  # skip divider lines 
 
491
      next if /^$/;   # skip blank lines
 
492
 
 
493
      next until /(Aborted_clients|back_log|=)/;
 
494
 
 
495
      if($1 eq 'Aborted_clients')  # status values
 
496
      {
 
497
         print "read_infile: start stats\n" if $op{debug};
 
498
 
 
499
         while($_)
 
500
         {
 
501
            chomp;
 
502
            if(/([A-Za-z_]+)[\s\t|]+(\d+)/)
 
503
            {
 
504
               $stats{$1} = $2;
 
505
               print "read_infile: save $1 = $2\n" if $op{debug};
 
506
            }
 
507
            else { print "read_infile: ignore '$_'\n" if $op{debug}; }
 
508
 
 
509
            last if $1 eq 'Uptime';  # exit while() if end of status values
 
510
            $_ = <INFILE>; # otherwise, read next line of status values
 
511
         }
 
512
      }
 
513
      elsif($1 eq  'back_log')  # system variable values
 
514
      {
 
515
         print "read_infile: start vars\n" if $op{debug};
 
516
 
 
517
         while($_)
 
518
         {
 
519
            chomp;
 
520
            if(/([A-Za-z_]+)[\s\t|]+([\w\.\-]+)/)  # This will exclude some vars
 
521
            {                                      # like pid_file which we don't need
 
522
               $vars{$1} = $2;
 
523
               print "read_infile: save $1 = $2\n" if $op{debug};
 
524
            }
 
525
            else { print "read_infile: ignore '$_'\n" if $op{debug}; }
 
526
 
 
527
            last if $1 eq 'wait_timeout';  # exit while() if end of vars
 
528
            $_ = <INFILE>; # otherwise, read next line of vars
 
529
         }
 
530
      }
 
531
      elsif($1 eq '=')  # old style, manually added system variable values
 
532
      {
 
533
         print "read_infile: start old vars\n" if $op{debug};
 
534
 
 
535
         while($_ && $_ =~ /=/)
 
536
         {
 
537
            chomp;
 
538
            if(/^\s*(\w+)\s*=\s*([0-9.]+)(M*)\s*$/)  # e.g.: key_buffer_size = 128M
 
539
            {
 
540
               $vars{$1} = ($3 ? $2 * 1024 * 1024 : $2);
 
541
               print "read_infile: read '$_' as $1 = $vars{$1}\n" if $op{debug};
 
542
            }
 
543
            else { print "read_infile: ignore '$_'\n" if $op{debug}; }
 
544
 
 
545
            $_ = <INFILE>; # otherwise, read next line of old vars
 
546
         }
 
547
 
 
548
         redo;
475
549
      }
476
550
      else
477
551
      {
478
552
         print "read_infile: unrecognized line: '$_'\n" if $op{debug};
479
553
      }
480
554
   }
 
555
 
481
556
   close INFILE;
482
557
 
483
558
   $real_uptime = $stats{'Uptime'};
489
564
 
490
565
sub get_MySQL_version
491
566
{
492
 
   return if $major;
 
567
   print "get_MySQL_version\n" if $op{debug};
 
568
 
 
569
   return if $MySQL_version;
 
570
 
 
571
   my ($major, $minor, $patch);
493
572
 
494
573
   if($op{'infile'} || $relative_infiles)
495
574
   {
505
584
      ($major, $minor, $patch) = ($row[1] =~ /(\d{1,2})\.(\d{1,2})\.(\d{1,2})/);
506
585
   }
507
586
 
 
587
   $MySQL_version = sprintf("%d%02d%02d", $major, $minor, $patch);
 
588
 
508
589
   # Innodb_ status values were added in 5.0.2
509
 
   if($major <= 4 || $patch < 2)
 
590
   if($MySQL_version < 50002)
510
591
   {
511
592
      $have_innodb_vals = 0;
512
593
      print "get_MySQL_version: no InnoDB reports because MySQL version is older than 5.0.2\n" if $op{debug};
515
596
 
516
597
sub set_myisam_vals
517
598
{
 
599
   print "set_myisam_vals\n" if $op{debug};
 
600
 
518
601
   $questions = $stats{'Questions'};
519
602
 
520
603
   $key_read_ratio = sprintf "%.2f",
554
637
 
555
638
   $dms = $DMS_vals{SELECT} + $DMS_vals{INSERT} + $DMS_vals{REPLACE} + $DMS_vals{UPDATE} + $DMS_vals{DELETE};
556
639
 
557
 
   $slow_query_t = "($vars{long_query_time})";
 
640
   $slow_query_t = format_u_time($vars{long_query_time});
558
641
 
559
642
}
560
643
 
561
644
sub set_ib_vals
562
645
{
 
646
   print "set_ib_vals\n" if $op{debug};
 
647
 
563
648
   $ib_bp_used  = ($stats{'Innodb_buffer_pool_pages_total'} -
564
649
                   $stats{'Innodb_buffer_pool_pages_free'}) *
565
650
                   $stats{'Innodb_page_size'};
575
660
 
576
661
sub write_relative_report
577
662
{
578
 
      %stats_present = %stats;
579
 
 
580
 
      for(keys %stats)
581
 
      {
582
 
         if($stats_past{$_} =~ /\d+/)
583
 
         {
584
 
            if($stats_present{$_} >= $stats_past{$_}) # Avoid negative values
585
 
            {
586
 
               $stats{$_} = $stats_present{$_} - $stats_past{$_};
587
 
            }
588
 
         }
589
 
      }
590
 
 
591
 
      # These values are either "at present" or "high water marks".
592
 
      # Therefore, it is more logical to not relativize these values.
593
 
      # Doing otherwise causes strange and misleading values.
594
 
      $stats{'Key_blocks_used'}      = $stats_present{'Key_blocks_used'};
595
 
      $stats{'Open_tables'}          = $stats_present{'Open_tables'};
596
 
      $stats{'Max_used_connections'} = $stats_present{'Max_used_connections'};
597
 
      $stats{'Threads_running'}      = $stats_present{'Threads_running'};
598
 
      $stats{'Threads_connected'}    = $stats_present{'Threads_connected'};
599
 
      $stats{'Threads_cached'}       = $stats_present{'Threads_cached'};
600
 
      $stats{'Qcache_free_blocks'}   = $stats_present{'Qcache_free_blocks'};
601
 
      $stats{'Qcache_total_blocks'}  = $stats_present{'Qcache_total_blocks'};
602
 
      $stats{'Qcache_free_memory'}   = $stats_present{'Qcache_free_memory'};
603
 
      if($have_innodb_vals)
604
 
      {
605
 
         $stats{'Innodb_page_size'}                 = $stats_present{'Innodb_page_size'};
606
 
         $stats{'Innodb_buffer_pool_pages_data'}    = $stats_present{'Innodb_buffer_pool_pages_data'};
607
 
         $stats{'Innodb_buffer_pool_pages_dirty'}   = $stats_present{'Innodb_buffer_pool_pages_dirty'};
608
 
         $stats{'Innodb_buffer_pool_pages_free'}    = $stats_present{'Innodb_buffer_pool_pages_free'};
609
 
         $stats{'Innodb_buffer_pool_pages_latched'} = $stats_present{'Innodb_buffer_pool_pages_latched'};
610
 
         $stats{'Innodb_buffer_pool_pages_misc'}    = $stats_present{'Innodb_buffer_pool_pages_misc'};
611
 
         $stats{'Innodb_buffer_pool_pages_total'}   = $stats_present{'Innodb_buffer_pool_pages_total'};
612
 
         $stats{'Innodb_data_pending_fsyncs'}       = $stats_present{'Innodb_data_pending_fsyncs'};
613
 
         $stats{'Innodb_data_pending_reads'}        = $stats_present{'Innodb_data_pending_reads'};
614
 
         $stats{'Innodb_data_pending_writes'}       = $stats_present{'Innodb_data_pending_writes'};
615
 
 
616
 
         # Innodb_row_lock_ values were added in MySQL 5.0.3
617
 
         if((($minor == 0 && $patch >= 3) || $minor > 0))
618
 
         {
619
 
            $stats{'Innodb_row_lock_current_waits'} = $stats_present{'Innodb_row_lock_current_waits'};
620
 
            $stats{'Innodb_row_lock_time_avg'}      = $stats_present{'Innodb_row_lock_time_avg'};
621
 
            $stats{'Innodb_row_lock_time_max'}      = $stats_present{'Innodb_row_lock_time_max'};
622
 
         }
623
 
      }
624
 
 
625
 
      get_Com_values();
626
 
 
627
 
      %stats_past = %stats_present;
628
 
 
629
 
      set_myisam_vals();
630
 
      set_ib_vals() if $have_innodb_vals;
631
 
 
632
 
      write_report();
 
663
   print "write_relative_report\n" if $op{debug};
 
664
 
 
665
   %stats_present = %stats;
 
666
 
 
667
   for(keys %stats)
 
668
   {
 
669
      if($stats_past{$_} =~ /\d+/)
 
670
      {
 
671
         if($stats_present{$_} >= $stats_past{$_}) # Avoid negative values
 
672
         {
 
673
            $stats{$_} = $stats_present{$_} - $stats_past{$_};
 
674
         }
 
675
      }
 
676
   }
 
677
 
 
678
   # These values are either "at present" or "high water marks".
 
679
   # Therefore, it is more logical to not relativize these values.
 
680
   # Doing otherwise causes strange and misleading values.
 
681
   $stats{'Key_blocks_used'}      = $stats_present{'Key_blocks_used'};
 
682
   $stats{'Open_tables'}          = $stats_present{'Open_tables'};
 
683
   $stats{'Max_used_connections'} = $stats_present{'Max_used_connections'};
 
684
   $stats{'Threads_running'}      = $stats_present{'Threads_running'};
 
685
   $stats{'Threads_connected'}    = $stats_present{'Threads_connected'};
 
686
   $stats{'Threads_cached'}       = $stats_present{'Threads_cached'};
 
687
   $stats{'Qcache_free_blocks'}   = $stats_present{'Qcache_free_blocks'};
 
688
   $stats{'Qcache_total_blocks'}  = $stats_present{'Qcache_total_blocks'};
 
689
   $stats{'Qcache_free_memory'}   = $stats_present{'Qcache_free_memory'};
 
690
   if($have_innodb_vals)
 
691
   {
 
692
      $stats{'Innodb_page_size'}                 = $stats_present{'Innodb_page_size'};
 
693
      $stats{'Innodb_buffer_pool_pages_data'}    = $stats_present{'Innodb_buffer_pool_pages_data'};
 
694
      $stats{'Innodb_buffer_pool_pages_dirty'}   = $stats_present{'Innodb_buffer_pool_pages_dirty'};
 
695
      $stats{'Innodb_buffer_pool_pages_free'}    = $stats_present{'Innodb_buffer_pool_pages_free'};
 
696
      $stats{'Innodb_buffer_pool_pages_latched'} = $stats_present{'Innodb_buffer_pool_pages_latched'};
 
697
      $stats{'Innodb_buffer_pool_pages_misc'}    = $stats_present{'Innodb_buffer_pool_pages_misc'};
 
698
      $stats{'Innodb_buffer_pool_pages_total'}   = $stats_present{'Innodb_buffer_pool_pages_total'};
 
699
      $stats{'Innodb_data_pending_fsyncs'}       = $stats_present{'Innodb_data_pending_fsyncs'};
 
700
      $stats{'Innodb_data_pending_reads'}        = $stats_present{'Innodb_data_pending_reads'};
 
701
      $stats{'Innodb_data_pending_writes'}       = $stats_present{'Innodb_data_pending_writes'};
 
702
 
 
703
      # Innodb_row_lock_ values were added in MySQL 5.0.3
 
704
      if($MySQL_version >= 50003)
 
705
      {
 
706
         $stats{'Innodb_row_lock_current_waits'} = $stats_present{'Innodb_row_lock_current_waits'};
 
707
         $stats{'Innodb_row_lock_time_avg'}      = $stats_present{'Innodb_row_lock_time_avg'};
 
708
         $stats{'Innodb_row_lock_time_max'}      = $stats_present{'Innodb_row_lock_time_max'};
 
709
      }
 
710
   }
 
711
 
 
712
   get_Com_values();
 
713
 
 
714
   %stats_past = %stats_present;
 
715
 
 
716
   set_myisam_vals();
 
717
   set_ib_vals() if $have_innodb_vals;
 
718
 
 
719
   write_report();
633
720
}
634
721
 
635
722
sub write_report
636
723
{
 
724
   print "write_report\n" if $op{debug};
 
725
 
637
726
   $~ = 'MYSQL_TIME', write;
638
727
   $~ = 'KEY_BUFF_MAX', write;
639
728
   if($key_buffer_usage != -1) { $~ = 'KEY_BUFF_USAGE', write }
692
781
   return $short;
693
782
}
694
783
 
 
784
# What began as a simple but great idea has become the new standard:
 
785
# long_query_time in microseconds. For MySQL 5.1.21+ and 6.0.4+ this
 
786
# is now standard. For 4.1 and 5.0 patches, the architects of this
 
787
# idea provide: http://www.mysqlperformanceblog.com/mysql-patches/
 
788
# Relevant notes in MySQL manual:
 
789
# http://dev.mysql.com/doc/refman/5.1/en/slow-query-log.html
 
790
# http://dev.mysql.com/doc/refman/6.0/en/slow-query-log.html
 
791
#
 
792
# The format_u_time sub simply beautifies long_query_time.
 
793
 
 
794
sub format_u_time  # format microsecond (�) time value
 
795
{
 
796
   # 0.000000 - 0.000999 = 0 - 999 �
 
797
   # 0.001000 - 0.999999 = 1 ms - 999.999 ms
 
798
   # 1.000000 - n.nnnnnn = 1 s - n.nnnnn s
 
799
 
 
800
   my $t = shift;
 
801
   my $f;  # formatted � time
 
802
   my $u = chr(($WIN ? 230 : 181));
 
803
 
 
804
   $t = 0 if $t < 0;
 
805
 
 
806
   if($t > 0 && $t <= 0.000999)
 
807
   {
 
808
      $f = ($t * 1000000) . " $u";
 
809
   }
 
810
   elsif($t >= 0.001000 && $t <= 0.999999)
 
811
   {
 
812
      $f = ($t * 1000) . ' ms';
 
813
   }
 
814
   elsif($t >= 1)
 
815
   {
 
816
      $f = ($t * 1) . ' s';  # * 1 to remove insignificant zeros
 
817
   }
 
818
   else
 
819
   {
 
820
      $f = 0;  # $t should = 0 at this point
 
821
   }
 
822
 
 
823
   return $f;
 
824
}
 
825
 
695
826
sub perc # Percentage
696
827
{
697
828
   my($is, $of) = @_;
 
829
   $is = 0 if (not defined $is);
698
830
   return sprintf "%.2f", ($is * 100) / ($of ||= 1);
699
831
}
700
832
 
707
839
 
708
840
sub email_report # Email given report to $op{'email'}
709
841
{
 
842
   print "email_report\n" if $op{debug};
 
843
 
710
844
   return if $WIN;
711
845
 
712
846
   my $report = shift;
721
855
 
722
856
sub cat_report # Print given report to screen
723
857
{
 
858
   print "cat_report\n" if $op{debug};
 
859
 
724
860
   my $report = shift;
725
861
   my @report;
726
862
 
732
868
 
733
869
sub get_Com_values
734
870
{
 
871
   print "get_Com_values\n" if $op{debug};
 
872
 
735
873
   %Com_vals = ();
736
874
 
737
875
   # Make copy of just the Com_ values
758
896
 
759
897
sub write_DTQ # Write DTQ report in descending order by values
760
898
{
 
899
   print "write_DTQ\n" if $op{debug};
 
900
 
761
901
   $~ = 'DTQ';
762
902
 
763
903
   my %DTQ;
792
932
 
793
933
sub write_DMS # Write DMS report in descending order by values
794
934
{
 
935
   print "write_DMS\n" if $op{debug};
 
936
 
795
937
   $~ = 'DMS';
796
938
 
797
939
   for(sort { $DMS_vals{$b} <=> $DMS_vals{$a} } keys(%DMS_vals))
804
946
 
805
947
sub write_Com # Write COM report in descending order by values
806
948
{
 
949
   print "write_Com\n" if $op{debug};
 
950
 
807
951
   my $i = $op{'com'};
808
952
 
809
953
   $~ = 'COM_1';
829
973
 
830
974
sub write_qcache
831
975
{
 
976
   print "write_qcache\n" if $op{debug};
 
977
 
832
978
   # Query cache was added in 4.0.1, but have_query_cache was added in 4.0.2,
833
979
   # ergo this method is slightly more reliable
834
980
   return if not exists $vars{'query_cache_size'};
844
990
 
845
991
sub write_InnoDB
846
992
{
847
 
   # Innodb_ status values were added in MySQL 5.0.2
848
 
   if(! ($major >= 5 && (($minor == 0 && $patch >= 2) || $minor > 0)) )
849
 
   {
850
 
      # In case infile has Innodb_ values but didn't specify the MySQL version
851
 
      if(not defined $stats{'Innodb_page_size'}) { return; }
852
 
   }
 
993
   print "write_InnoDB\n" if $op{debug};
 
994
 
 
995
   return if not defined $stats{'Innodb_page_size'};
 
996
 
 
997
   $stats{'Innodb_buffer_pool_pages_latched'} = 0 if not defined $stats{'Innodb_buffer_pool_pages_latched'};
853
998
 
854
999
   $~ = 'IB';
855
1000
   write;
856
1001
 
857
1002
   # Innodb_row_lock_ values were added in MySQL 5.0.3
858
 
   if((($minor == 0 && $patch >= 3) || $minor > 0))
 
1003
   if($MySQL_version >= 50003)
859
1004
   {
860
1005
      $~ = 'IB_LOCK';
861
1006
      write;
882
1027
 
883
1028
sub exit_tasks_and_cleanup
884
1029
{
 
1030
   print "exit_tasks_and_cleanup\n" if $op{debug};
 
1031
 
885
1032
   close $tmpfile_fh;
886
1033
   select STDOUT unless $op{'detach'};
887
1034
 
951
1098
.
952
1099
 
953
1100
format SLOW_DMS =
954
 
Slow @<<<<< @>>>>>>>>  @>>>>>/s          @>>>>>  %DMS: @>>>>>  Log: @>> 
 
1101
Slow @<<<<<<< @>>>>>>  @>>>>>/s          @>>>>>  %DMS: @>>>>>  Log: @>> 
955
1102
$slow_query_t, make_short($stats{'Slow_queries'}), t($stats{'Slow_queries'}), perc($stats{'Slow_queries'}, $questions), perc($stats{'Slow_queries'}, $dms), $vars{'log_slow_queries'}
956
1103
DMS         @>>>>>>>>  @>>>>>/s          @>>>>>
957
1104
make_short($dms), t($dms), perc($dms, $questions)