source: pkg/security/vinnie/main/mysql-5.1/trunk/debian/additions/mysqlreport @ 6989

Revision 6989, 38.1 KB checked in by alanbach-guest, 3 years ago (diff)
  • Updated mysql-5.1 from lenny-backports
Line 
1#!/usr/bin/perl -w
2
3# mysqlreport v3.5 Apr 16 2008
4# http://hackmysql.com/mysqlreport
5
6# mysqlreport makes an easy-to-read report of important MySQL status values.
7# Copyright 2006-2008 Daniel Nichter
8#
9# This program is free software; you can redistribute it and/or
10# modify it under the terms of the GNU General Public License
11# as published by the Free Software Foundation; either version 2
12# of the License, or (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# The GNU General Public License is available at:
20# http://www.gnu.org/copyleft/gpl.html
21
22use strict;
23use File::Temp qw(tempfile);
24use DBI;
25use Getopt::Long;
26eval { require Term::ReadKey; };
27my $RK = ($@ ? 0 : 1);
28
29sub have_op;
30
31my $WIN = ($^O eq 'MSWin32' ? 1 : 0);
32my %op;
33my %mycnf; # ~/.my.cnf
34my ($tmpfile_fh, $tmpfile);
35my ($stat_name, $stat_val, $stat_label);
36my $MySQL_version;
37my (%stats, %vars); # SHOW STATUS, SHOW VARIABLES
38my (%DMS_vals, %Com_vals, %ib_vals);
39my ($dbh, $query);
40my ($questions, $key_read_ratio, $key_write_ratio, $dms, $slow_query_t);
41my ($key_cache_block_size, $key_buffer_used, $key_buffer_usage);
42my ($qc_mem_used, $qc_hi_r, $qc_ip_r); # Query Cache
43my $have_innodb_vals;
44my ($ib_bp_used, $ib_bp_total, $ib_bp_read_ratio);
45my ($relative_live, $relative_infiles);
46my $real_uptime;
47my (%stats_present, %stats_past); # For relative reports
48     
49GetOptions (
50   \%op,
51   "user=s",
52   "password:s",
53   "host=s",
54   "port=s",
55   "socket=s",
56   "no-mycnf",
57   "infile|in=s",
58   "outfile=s",
59   "flush-status",
60   "email=s",
61   "r|relative:i",
62   "c|report-count=i",
63   "detach",
64   "help|?",
65   "debug"
66);
67
68show_help_and_exit() if $op{'help'};
69
70get_user_mycnf() unless $op{'no-mycnf'};
71
72# Command line options override ~/.my.cnf
73$mycnf{'host'}   = $op{'host'}   if have_op 'host';
74$mycnf{'port'}   = $op{'port'}   if have_op 'port';
75$mycnf{'socket'} = $op{'socket'} if have_op 'socket'; 
76$mycnf{'user'}   = $op{'user'}   if have_op 'user';
77
78$mycnf{'user'} ||= $ENV{'USER'};
79
80if(exists $op{'password'})
81{
82   if($op{'password'} eq '') # Prompt for password
83   {
84      Term::ReadKey::ReadMode(2) if $RK;
85      print "Password for database user $mycnf{'user'}: ";
86      chomp($mycnf{'pass'} = <STDIN>);
87      Term::ReadKey::ReadMode(0), print "\n" if $RK;
88   }
89   else { $mycnf{'pass'} = $op{'password'}; } # Use password given on command line
90}
91
92$op{'com'} ||= 3;
93$op{'c'}   ||= 1; # Used in collect_reports() if --r given integer value
94
95$relative_live    = 0;
96$relative_infiles = 0;
97
98if(defined $op{'r'})
99{
100   if($op{r}) { $relative_live    = 1; }  # if -r was given an integer value
101   else       { $relative_infiles = 1; }
102}
103
104# The report is written to a tmp file first.
105# Later it will be moved to $op{'outfile'} or emailed $op{'email'} if needed.
106($tmpfile_fh, $tmpfile) = tempfile() or die "Cannot open temporary file for writing: $!\n";
107
108if($op{'detach'})
109{
110   $SIG{'TERM'} = 'sig_handler';
111
112   if(fork())
113   {
114      print "mysqlreport has forked and detached.\n";
115      print "While running detached, mysqlreport writes reports to '$tmpfile'.\n";
116
117      exit;
118   }
119
120   open(STDIN, "</dev/null");
121   open(STDOUT, "> $tmpfile") or die "Cannot dup STDOUT: $!\n";
122   open(STDERR, "> $tmpfile") or die "Cannot dup STDERR: $!\n";
123}
124
125select $tmpfile_fh;
126$| = 1 if ($op{'detach'} || $relative_live);
127
128print "tmp file: $tmpfile\n" if $op{debug};
129
130# Connect to MySQL
131if(!$op{'infile'} && !$relative_infiles)
132{
133   connect_to_MySQL();
134}
135
136$have_innodb_vals = 1; # This might be set to 0 later in get_MySQL_version()
137
138if(defined $op{'r'})
139{
140   if($relative_live)
141   { 
142      print STDERR "mysqlreport is writing relative reports to '$tmpfile'.\n" unless $op{'detach'}; 
143      get_MySQL_version();
144      collect_reports();
145   }
146
147   if($relative_infiles) { read_relative_infiles(); }
148}
149else
150{
151   if(!$op{'infile'})
152   {
153      get_MySQL_version();
154      get_vals();
155      get_vars();
156   }
157   else
158   {
159      read_infile($op{'infile'});
160   }
161
162   get_Com_values();
163
164   set_myisam_vals();
165   set_ib_vals() if $have_innodb_vals;
166
167   write_report();
168}
169
170exit_tasks_and_cleanup();
171
172exit;
173
174#
175# Subroutines
176#
177sub show_help_and_exit
178{
179   print <<"HELP";
180mysqlreport v3.5 Apr 16 2008
181mysqlreport makes an easy-to-read report of important MySQL status values.
182
183Command line options (abbreviations work):
184   --user USER       Connect to MySQL as USER
185   --password PASS   Use PASS or prompt for MySQL user's password
186   --host ADDRESS    Connect to MySQL at ADDRESS
187   --port PORT       Connect to MySQL at PORT
188   --socket SOCKET   Connect to MySQL at SOCKET
189   --no-mycnf        Don't read ~/.my.cnf
190   --infile FILE     Read status values from FILE instead of MySQL
191   --outfile FILE    Write report to FILE
192   --email ADDRESS   Email report to ADDRESS (doesn't work on Windows)
193   --flush-status    Issue FLUSH STATUS; after getting current values
194   --relative X      Generate relative reports. If X is an integer,
195                     reports are live from the MySQL server X seconds apart.
196                     If X is a list of infiles (file1 file2 etc.),
197                     reports are generated from the infiles in the order
198                     that they are given.
199   --report-count N  Collect N number of live relative reports (default 1)
200   --detach          Fork and detach from terminal (run in background)
201   --help            Prints this
202   --debug           Print debugging information
203
204Visit http://hackmysql.com/mysqlreport for more information.
205HELP
206
207   exit;
208}
209
210sub get_user_mycnf
211{
212   print "get_user_mycnf\n" if $op{debug};
213
214   return if $WIN;
215   open MYCNF, "$ENV{HOME}/.my.cnf" or return;
216   while(<MYCNF>)
217   {
218      if(/^(.+?)\s*=\s*"?(.+?)"?\s*$/)
219      {
220         $mycnf{$1} = $2;
221         print "get_user_mycnf: read '$1 = $2'\n" if $op{debug};
222      }
223   }
224   $mycnf{'pass'} ||= $mycnf{'password'} if exists $mycnf{'password'};
225   close MYCNF;
226}
227
228sub 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
252sub collect_reports
253{
254   print "collect_reports\n" if $op{debug};
255
256   my $i;
257
258   get_vals();
259   get_vars();
260
261   get_Com_values();
262
263   %stats_past = %stats;
264
265   set_myisam_vals();
266   set_ib_vals() if $have_innodb_vals;
267
268   print "#\n# Beginning report, 0 0:0:0\n#\n";
269
270   write_report();
271
272   for($i = 0; $i < $op{'c'}; $i++)
273   {
274      $dbh->disconnect();
275
276      sleep($op{'r'});
277
278      connect_to_MySQL();
279
280      print "\n#\n# Interval report " , $i + 1 , ", +", sec_to_dhms(($i + 1) * $op{'r'}), "\n#\n";
281
282      get_vals();
283
284      write_relative_report();
285   }
286}
287
288sub read_relative_infiles
289{
290   print "read_relative_infiles\n" if $op{debug};
291
292   my $slurp;    # Used to check infiles for multiple sets of status values
293   my $n_stats;  # Number of multiple sets of status values in an infile
294   my $infile;
295   my $report_n; # Report number
296
297   $report_n = 1;
298
299   foreach $infile (@ARGV)
300   {
301      # Read all of infile into $slurp
302      open INFILE, "< $infile" or warn and next;
303      $slurp = do { local $/;  <INFILE> };
304      close INFILE;
305
306      $n_stats = 0;
307
308      # Count number of status value sets
309      $n_stats++ while $slurp =~ /Aborted_clients/g;
310
311      print "read_relative_infiles: found $n_stats sets of status values in file '$infile'\n"
312         if $op{debug};
313
314      if($n_stats == 1)
315      {
316         read_infile($infile);
317         relative_infile_report($report_n++);
318      }
319
320      if($n_stats > 1)
321      {
322         my @tmpfile_fh;
323         my @tmpfile_name;
324         my $i;
325         my $stat_n;  # Status value set number
326
327         # Create a tmp file for each set of status values
328         for($i = 0; $i < $n_stats; $i++)
329         {
330            my ($fh, $name) = tempfile()
331               or die "read_relative_infiles: cannot open temporary file for writing: $!\n";
332
333            push(@tmpfile_fh, $fh);
334            push(@tmpfile_name, $name);
335
336            print "read_relative_infiles: created tmp file '$name' for set $i\n" if $op{debug};
337         }
338
339         $i = 0;
340         $stat_n = 0;
341
342         select $tmpfile_fh[$i];
343
344         # Read infile again and copy each set of status values to seperate tmp files
345         open INFILE, "< $infile" or warn and next;
346         while(<INFILE>)
347         {
348            next if /^\+/;
349            next if /^$/;
350
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.
357
358            if(/Aborted_clients/)
359            {
360               print and next if $stat_n++ == 0;
361               select $tmpfile_fh[++$i];
362            }
363
364            print;
365         }
366         close INFILE;
367
368         # Re-select the main tmp file into which the reports are being written.
369         select $tmpfile_fh;
370
371         for($i = 0; $i < $n_stats; $i++)
372         {
373            close $tmpfile_fh[$i];
374
375            print "read_relative_infiles: reading set $i tmp file '$tmpfile_name[$i]'\n"
376               if $op{debug};
377
378            read_infile($tmpfile_name[$i]);
379            relative_infile_report($report_n++);
380
381            if($WIN) { `del $tmpfile_name[$i]`;   }
382            else     { `rm -f $tmpfile_name[$i]`; }
383
384            print "read_relative_infiles: deleted set $i tmp file '$tmpfile_name[$i]'\n"
385               if $op{debug};
386         }
387
388      } # if($n_stats > 1)
389   } # foreach $infile (@files)
390}
391
392sub relative_infile_report
393{
394   print "relative_infile_report\n" if $op{debug};
395
396   my $report_n = shift;
397
398   if($report_n == 1)
399   {
400      get_Com_values();
401
402      %stats_past = %stats;
403
404      set_myisam_vals();
405      set_ib_vals() if $have_innodb_vals;
406
407      print "#\n# Beginning report, 0 0:0:0\n#\n";
408
409      write_report();
410   }
411   else
412   {
413      print "\n#\n# Interval report ", $report_n - 1, ", +",
414         sec_to_dhms($stats{Uptime} - $stats_past{Uptime}),
415         "\n#\n";
416
417      write_relative_report();
418   }
419}
420
421sub get_vals
422{
423   print "get_vals\n" if $op{debug};
424
425   my @row;
426
427   # Get status values
428   if($MySQL_version >= 50002)
429   {
430      $query = $dbh->prepare("SHOW GLOBAL STATUS;");
431   }
432   else
433   {
434      $query = $dbh->prepare("SHOW STATUS;");
435   }
436   $query->execute();
437   while(@row = $query->fetchrow_array()) { $stats{$row[0]} = $row[1]; }
438
439   $real_uptime = $stats{'Uptime'};
440}
441
442sub get_vars
443{
444   print "get_vars\n" if $op{debug};
445
446   my @row;
447
448   # Get server system variables
449   $query = $dbh->prepare("SHOW VARIABLES;");
450   $query->execute();
451   while(@row = $query->fetchrow_array()) { $vars{$row[0]} = $row[1]; }
452
453   # table_cache was renamed to table_open_cache in MySQL 5.1.3
454   if($MySQL_version >= 50103)
455   {
456      $vars{'table_cache'} = $vars{'table_open_cache'};
457   }
458}
459
460sub read_infile
461{
462   print "read_infile\n" if $op{debug};
463
464   my $infile = shift;
465
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.
470   $vars{'version'} = "0.0.0"         if !exists $vars{'version'};
471   $vars{'table_cache'} = 64          if !exists $vars{'table_cache'};
472   $vars{'max_connections'} = 100     if !exists $vars{'max_connections'};
473   $vars{'key_buffer_size'} = 8388600 if !exists $vars{'key_buffer_size'}; # 8M
474   $vars{'thread_cache_size'} = 0     if !exists $vars{'thread_cache_size'}; 
475   $vars{'tmp_table_size'} = 0        if !exists $vars{'tmp_table_size'};
476   $vars{'long_query_time'} = '?'     if !exists $vars{'long_query_time'};
477   $vars{'log_slow_queries'} = '?'    if !exists $vars{'log_slow_queries'};
478
479   # One should also add:
480   #    key_cache_block_size
481   #    query_cache_size
482   # to INFILE if needed.
483
484   open INFILE, "< $infile" or die "Cannot open INFILE '$infile': $!\n";
485
486   while(<INFILE>)
487   {
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;
549      }
550      else
551      {
552         print "read_infile: unrecognized line: '$_'\n" if $op{debug};
553      }
554   }
555
556   close INFILE;
557
558   $real_uptime = $stats{'Uptime'};
559
560   $vars{'table_cache'} = $vars{'table_open_cache'} if exists $vars{'table_open_cache'};
561
562   get_MySQL_version();
563}
564
565sub get_MySQL_version
566{
567   print "get_MySQL_version\n" if $op{debug};
568
569   return if $MySQL_version;
570
571   my ($major, $minor, $patch);
572
573   if($op{'infile'} || $relative_infiles)
574   {
575      ($major, $minor, $patch) = ($vars{'version'} =~ /(\d{1,2})\.(\d{1,2})\.(\d{1,2})/);
576   }
577   else
578   {
579      my @row;
580
581      $query = $dbh->prepare("SHOW VARIABLES LIKE 'version';");
582      $query->execute();
583      @row = $query->fetchrow_array();
584      ($major, $minor, $patch) = ($row[1] =~ /(\d{1,2})\.(\d{1,2})\.(\d{1,2})/);
585   }
586
587   $MySQL_version = sprintf("%d%02d%02d", $major, $minor, $patch);
588
589   # Innodb_ status values were added in 5.0.2
590   if($MySQL_version < 50002)
591   {
592      $have_innodb_vals = 0;
593      print "get_MySQL_version: no InnoDB reports because MySQL version is older than 5.0.2\n" if $op{debug};
594   }
595}
596
597sub set_myisam_vals
598{
599   print "set_myisam_vals\n" if $op{debug};
600
601   $questions = $stats{'Questions'};
602
603   $key_read_ratio = sprintf "%.2f",
604                     ($stats{'Key_read_requests'} ?
605                      100 - ($stats{'Key_reads'} / $stats{'Key_read_requests'}) * 100 :
606                      0);
607
608   $key_write_ratio = sprintf "%.2f",
609                      ($stats{'Key_write_requests'} ?
610                       100 - ($stats{'Key_writes'} / $stats{'Key_write_requests'}) * 100 :
611                       0);
612
613   $key_cache_block_size = (defined $vars{'key_cache_block_size'} ?
614                            $vars{'key_cache_block_size'} :
615                            1024);
616
617   $key_buffer_used = $stats{'Key_blocks_used'} * $key_cache_block_size;
618
619   if(defined $stats{'Key_blocks_unused'}) # MySQL 4.1.2+
620   {
621      $key_buffer_usage =  $vars{'key_buffer_size'} -
622                           ($stats{'Key_blocks_unused'} * $key_cache_block_size);
623   }
624   else { $key_buffer_usage = -1; }
625
626   # Data Manipulation Statements: http://dev.mysql.com/doc/refman/5.0/en/data-manipulation.html
627   %DMS_vals =
628   (
629      SELECT  => $stats{'Com_select'},
630      INSERT  => $stats{'Com_insert'}  + $stats{'Com_insert_select'},
631      REPLACE => $stats{'Com_replace'} + $stats{'Com_replace_select'},
632      UPDATE  => $stats{'Com_update'}  +
633                 (exists $stats{'Com_update_multi'} ? $stats{'Com_update_multi'} : 0),
634      DELETE  => $stats{'Com_delete'}  +
635                 (exists $stats{'Com_delete_multi'} ? $stats{'Com_delete_multi'} : 0)
636   );
637
638   $dms = $DMS_vals{SELECT} + $DMS_vals{INSERT} + $DMS_vals{REPLACE} + $DMS_vals{UPDATE} + $DMS_vals{DELETE};
639
640   $slow_query_t = format_u_time($vars{long_query_time});
641
642}
643
644sub set_ib_vals
645{
646   print "set_ib_vals\n" if $op{debug};
647
648   $ib_bp_used  = ($stats{'Innodb_buffer_pool_pages_total'} -
649                   $stats{'Innodb_buffer_pool_pages_free'}) *
650                   $stats{'Innodb_page_size'};
651
652   $ib_bp_total = $stats{'Innodb_buffer_pool_pages_total'} * $stats{'Innodb_page_size'};
653
654   $ib_bp_read_ratio = sprintf "%.2f",
655                       ($stats{'Innodb_buffer_pool_read_requests'} ?
656                        100 - ($stats{'Innodb_buffer_pool_reads'} /
657                           $stats{'Innodb_buffer_pool_read_requests'}) * 100 :
658                        0);
659}
660
661sub write_relative_report
662{
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();
720}
721
722sub write_report
723{
724   print "write_report\n" if $op{debug};
725
726   $~ = 'MYSQL_TIME', write;
727   $~ = 'KEY_BUFF_MAX', write;
728   if($key_buffer_usage != -1) { $~ = 'KEY_BUFF_USAGE', write }
729   $~ = 'KEY_RATIOS', write;
730   write_DTQ();
731   $~ = 'SLOW_DMS', write;
732   write_DMS();
733   write_Com();
734   $~ = 'SAS', write; 
735   write_qcache(); 
736   $~ = 'REPORT_END', write;
737   $~ = 'TAB', write;
738
739   write_InnoDB() if $have_innodb_vals;
740}
741
742sub sec_to_dhms # Seconds to days hours:minutes:seconds
743{
744   my $s = shift;
745   my ($d, $h, $m) = (0, 0, 0);
746
747   return '0 0:0:0' if $s <= 0;
748
749   if($s >= 86400)
750   {
751      $d = int $s / 86400;
752      $s -= $d * 86400;
753   }
754
755   if($s >= 3600)
756   {
757     $h = int $s / 3600;
758     $s -= $h * 3600;
759   }
760   
761   $m = int $s / 60;
762   $s -= $m * 60;
763   
764   return "$d $h:$m:$s";
765}
766
767sub make_short
768{
769   my ($number, $kb, $d) = @_;
770   my $n = 0;
771   my $short;
772
773   $d ||= 2;
774
775   if($kb) { while ($number > 1023) { $number /= 1024; $n++; }; }
776   else { while ($number > 999) { $number /= 1000; $n++; }; }
777
778   $short = sprintf "%.${d}f%s", $number, ('','k','M','G','T')[$n];
779   if($short =~ /^(.+)\.(00)$/) { return $1; } # 12.00 -> 12 but not 12.00k -> 12k
780
781   return $short;
782}
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
794sub 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
826sub perc # Percentage
827{
828   my($is, $of) = @_;
829   $is = 0 if (not defined $is);
830   return sprintf "%.2f", ($is * 100) / ($of ||= 1);
831}
832
833sub t # Time average per second
834{
835   my $val = shift;
836   return 0 if !$val;
837   return(make_short($val / $stats{'Uptime'}, 0, 1));
838}
839
840sub email_report # Email given report to $op{'email'}
841{
842   print "email_report\n" if $op{debug};
843
844   return if $WIN;
845
846   my $report = shift;
847
848   open SENDMAIL, "|/usr/sbin/sendmail -t";
849   print SENDMAIL "From: mysqlreport\n";
850   print SENDMAIL "To: $op{email}\n";
851   print SENDMAIL "Subject: MySQL status report on " . ($mycnf{'host'} || 'localhost') . "\n\n";
852   print SENDMAIL `cat $report`;
853   close SENDMAIL;
854}
855
856sub cat_report # Print given report to screen
857{
858   print "cat_report\n" if $op{debug};
859
860   my $report = shift;
861   my @report;
862
863   open REPORT, "< $report";
864   @report = <REPORT>;
865   close REPORT;
866   print @report;
867}
868
869sub get_Com_values
870{
871   print "get_Com_values\n" if $op{debug};
872
873   %Com_vals = ();
874
875   # Make copy of just the Com_ values
876   for(keys %stats)
877   {
878      if(grep /^Com_/, $_ and $stats{$_} > 0)
879      {
880         /^Com_(.*)/;
881         $Com_vals{$1} = $stats{$_};
882      }
883   }
884
885   # Remove DMS values
886   delete $Com_vals{'select'};
887   delete $Com_vals{'insert'};
888   delete $Com_vals{'insert_select'};
889   delete $Com_vals{'replace'};
890   delete $Com_vals{'replace_select'};
891   delete $Com_vals{'update'};
892   delete $Com_vals{'update_multi'} if exists $Com_vals{'update_multi'};
893   delete $Com_vals{'delete'};
894   delete $Com_vals{'delete_multi'} if exists $Com_vals{'delete_multi'};
895}
896
897sub write_DTQ # Write DTQ report in descending order by values
898{
899   print "write_DTQ\n" if $op{debug};
900
901   $~ = 'DTQ';
902
903   my %DTQ;
904   my $first = 1;
905
906   # Total Com values
907   $stat_val = 0;
908   for(values %Com_vals) { $stat_val += $_; }
909   $DTQ{'Com_'} = $stat_val;
910
911   $DTQ{'DMS'}      = $dms;
912   $DTQ{'QC Hits'}  = $stats{'Qcache_hits'} if $stats{'Qcache_hits'} != 0;
913   $DTQ{'COM_QUIT'} = int (($stats{'Connections'} - 2) - ($stats{'Aborted_clients'} / 2));
914
915   $stat_val = 0;
916   for(values %DTQ) { $stat_val += $_; }
917   if($questions != $stat_val)
918   {
919      $DTQ{($questions > $stat_val ? '+Unknown' : '-Unknown')} = abs $questions - $stat_val;
920   }
921
922   for(sort { $DTQ{$b} <=> $DTQ{$a} } keys(%DTQ))
923   {
924      if($first) { $stat_label = '%Total:'; $first = 0; }
925      else       { $stat_label = ''; }
926
927      $stat_name = $_;
928      $stat_val  = $DTQ{$_};
929      write;
930   }
931}
932
933sub write_DMS # Write DMS report in descending order by values
934{
935   print "write_DMS\n" if $op{debug};
936
937   $~ = 'DMS';
938
939   for(sort { $DMS_vals{$b} <=> $DMS_vals{$a} } keys(%DMS_vals))
940   {
941      $stat_name = $_;
942      $stat_val  = $DMS_vals{$_};
943      write;
944   }
945}
946
947sub write_Com # Write COM report in descending order by values
948{
949   print "write_Com\n" if $op{debug};
950
951   my $i = $op{'com'};
952
953   $~ = 'COM_1';
954
955   # Total Com values and write first line of COM report
956   $stat_label = '%Total:' unless $op{'dtq'};
957   $stat_val   = 0;
958   for(values %Com_vals) { $stat_val += $_; }
959   write;
960
961   $~ = 'COM_2';
962
963   # Sort remaining Com values, print only the top $op{'com'} number of values
964   for(sort { $Com_vals{$b} <=> $Com_vals{$a} } keys(%Com_vals))
965   {
966      $stat_name = $_;
967      $stat_val  = $Com_vals{$_};
968      write;
969
970      last if !(--$i);
971   }
972}
973
974sub write_qcache
975{
976   print "write_qcache\n" if $op{debug};
977
978   # Query cache was added in 4.0.1, but have_query_cache was added in 4.0.2,
979   # ergo this method is slightly more reliable
980   return if not exists $vars{'query_cache_size'};
981   return if $vars{'query_cache_size'} == 0;
982
983   $qc_mem_used = $vars{'query_cache_size'} - $stats{'Qcache_free_memory'};
984   $qc_hi_r = sprintf "%.2f", $stats{'Qcache_hits'} / ($stats{'Qcache_inserts'} ||= 1);
985   $qc_ip_r = sprintf "%.2f", $stats{'Qcache_inserts'} / ($stats{'Qcache_lowmem_prunes'} ||= 1);
986
987   $~ = 'QCACHE';
988   write;
989}
990
991sub write_InnoDB
992{
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'};
998
999   $~ = 'IB';
1000   write;
1001
1002   # Innodb_row_lock_ values were added in MySQL 5.0.3
1003   if($MySQL_version >= 50003)
1004   {
1005      $~ = 'IB_LOCK';
1006      write;
1007   }
1008
1009   # Data, Pages, Rows
1010   $~ = 'IB_DPR';
1011   write;
1012}
1013
1014sub have_op
1015{
1016   my $key = shift;
1017   return 1 if (exists $op{$key} && $op{$key} ne '');
1018   return 0;
1019}
1020
1021sub sig_handler
1022{
1023   print "\nReceived signal at " , scalar localtime , "\n";
1024   exit_tasks_and_cleanup();
1025   exit;
1026}
1027
1028sub exit_tasks_and_cleanup
1029{
1030   print "exit_tasks_and_cleanup\n" if $op{debug};
1031
1032   close $tmpfile_fh;
1033   select STDOUT unless $op{'detach'};
1034
1035   email_report($tmpfile) if $op{'email'};
1036
1037   cat_report($tmpfile) unless $op{'detach'};
1038
1039   if($op{'outfile'})
1040   {
1041      if($WIN) { `move $tmpfile $op{outfile}`; }
1042      else     { `mv $tmpfile $op{outfile}`;   }
1043   }
1044   else
1045   {
1046      if($WIN) { `del $tmpfile`;   }
1047      else     { `rm -f $tmpfile`; }
1048   }
1049
1050   if(!$op{'infile'} && !$relative_infiles)
1051   {
1052      if($op{'flush-status'})
1053      {
1054         $query = $dbh->prepare("FLUSH STATUS;");
1055         $query->execute();
1056      }
1057
1058      $query->finish();
1059      $dbh->disconnect();
1060   }
1061}
1062
1063#
1064# Formats
1065#
1066
1067format MYSQL_TIME =
1068MySQL @<<<<<<<<<<<<<<<<  uptime @<<<<<<<<<<<   @>>>>>>>>>>>>>>>>>>>>>>>>
1069$vars{'version'}, sec_to_dhms($real_uptime), (($op{infile} || $relative_infiles) ? '' : scalar localtime)
1070.
1071
1072format KEY_BUFF_MAX =
1073
1074__ Key _________________________________________________________________
1075Buffer used   @>>>>>> of @>>>>>>  %Used: @>>>>>
1076make_short($key_buffer_used, 1), make_short($vars{'key_buffer_size'}, 1), perc($key_buffer_used, $vars{'key_buffer_size'})
1077.
1078
1079format KEY_BUFF_USAGE =
1080  Current     @>>>>>>            %Usage: @>>>>>
1081make_short($key_buffer_usage, 1), perc($key_buffer_usage, $vars{'key_buffer_size'})
1082.
1083
1084format KEY_RATIOS =
1085Write hit     @>>>>>%
1086$key_write_ratio
1087Read hit      @>>>>>%
1088$key_read_ratio
1089
1090__ Questions ___________________________________________________________
1091Total       @>>>>>>>>  @>>>>>/s
1092make_short($questions), t($questions)
1093.
1094
1095format DTQ =
1096  @<<<<<<<  @>>>>>>>>  @>>>>>/s  @>>>>>> @>>>>>
1097$stat_name, make_short($stat_val), t($stat_val), $stat_label, perc($stat_val, $questions)
1098.
1099
1100format SLOW_DMS =
1101Slow @<<<<<<< @>>>>>>  @>>>>>/s          @>>>>>  %DMS: @>>>>>  Log: @>>
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'}
1103DMS         @>>>>>>>>  @>>>>>/s          @>>>>>
1104make_short($dms), t($dms), perc($dms, $questions)
1105.
1106
1107format DMS =
1108  @<<<<<<<  @>>>>>>>>  @>>>>>/s          @>>>>>        @>>>>>
1109$stat_name, make_short($stat_val), t($stat_val), perc($stat_val, $questions), perc($stat_val, $dms)
1110.
1111
1112format COM_1 =
1113Com_        @>>>>>>>>  @>>>>>/s          @>>>>>
1114make_short($stat_val), t($stat_val), perc($stat_val, $questions)
1115.
1116
1117format COM_2 =
1118  @<<<<<<<<<< @>>>>>>  @>>>>>/s          @>>>>>
1119$stat_name, make_short($stat_val), t($stat_val), perc($stat_val, $questions)
1120.
1121
1122format SAS =
1123
1124__ SELECT and Sort _____________________________________________________
1125Scan          @>>>>>>   @>>>>/s %SELECT: @>>>>>
1126make_short($stats{'Select_scan'}), t($stats{'Select_scan'}), perc($stats{'Select_scan'}, $stats{'Com_select'})
1127Range         @>>>>>>   @>>>>/s          @>>>>>
1128make_short($stats{'Select_range'}), t($stats{'Select_range'}), perc($stats{'Select_range'}, $stats{'Com_select'})
1129Full join     @>>>>>>   @>>>>/s          @>>>>>
1130make_short($stats{'Select_full_join'}), t($stats{'Select_full_join'}), perc($stats{'Select_full_join'}, $stats{'Com_select'})
1131Range check   @>>>>>>   @>>>>/s          @>>>>>
1132make_short($stats{'Select_range_check'}), t($stats{'Select_range_check'}), perc($stats{'Select_range_check'}, $stats{'Com_select'})
1133Full rng join @>>>>>>   @>>>>/s          @>>>>>
1134make_short($stats{'Select_full_range_join'}), t($stats{'Select_full_range_join'}), perc($stats{'Select_full_range_join'}, $stats{'Com_select'})
1135Sort scan     @>>>>>>   @>>>>/s
1136make_short($stats{'Sort_scan'}), t($stats{'Sort_scan'})
1137Sort range    @>>>>>>   @>>>>/s
1138make_short($stats{'Sort_range'}), t($stats{'Sort_range'})
1139Sort mrg pass @>>>>>>   @>>>>/s
1140make_short($stats{'Sort_merge_passes'}), t($stats{'Sort_merge_passes'})
1141.
1142
1143format QCACHE =
1144
1145__ Query Cache _________________________________________________________
1146Memory usage  @>>>>>> of @>>>>>>  %Used: @>>>>>
1147make_short($qc_mem_used, 1), make_short($vars{'query_cache_size'}, 1), perc($qc_mem_used, $vars{'query_cache_size'})
1148Block Fragmnt @>>>>>%
1149perc($stats{'Qcache_free_blocks'}, $stats{'Qcache_total_blocks'})
1150Hits          @>>>>>>   @>>>>/s
1151make_short($stats{'Qcache_hits'}), t($stats{'Qcache_hits'})
1152Inserts       @>>>>>>   @>>>>/s
1153make_short($stats{'Qcache_inserts'}), t($stats{'Qcache_inserts'})
1154Insrt:Prune @>>>>>>:1   @>>>>/s
1155make_short($qc_ip_r), t($stats{'Qcache_inserts'} - $stats{'Qcache_lowmem_prunes'})
1156Hit:Insert  @>>>>>>:1
1157$qc_hi_r, t($qc_hi_r)
1158.
1159
1160# Not really the end...
1161format REPORT_END =
1162
1163__ Table Locks _________________________________________________________
1164Waited      @>>>>>>>>  @>>>>>/s  %Total: @>>>>>
1165make_short($stats{'Table_locks_waited'}), t($stats{'Table_locks_waited'}), perc($stats{'Table_locks_waited'}, $stats{'Table_locks_waited'} + $stats{'Table_locks_immediate'});
1166Immediate   @>>>>>>>>  @>>>>>/s
1167make_short($stats{'Table_locks_immediate'}), t($stats{'Table_locks_immediate'})
1168
1169__ Tables ______________________________________________________________
1170Open        @>>>>>>>> of @>>>    %Cache: @>>>>>
1171$stats{'Open_tables'}, $vars{'table_cache'}, perc($stats{'Open_tables'}, $vars{'table_cache'})
1172Opened      @>>>>>>>>  @>>>>>/s
1173make_short($stats{'Opened_tables'}), t($stats{'Opened_tables'})
1174
1175__ Connections _________________________________________________________
1176Max used    @>>>>>>>> of @>>>      %Max: @>>>>>
1177$stats{'Max_used_connections'}, $vars{'max_connections'}, perc($stats{'Max_used_connections'}, $vars{'max_connections'})
1178Total       @>>>>>>>>  @>>>>>/s
1179make_short($stats{'Connections'}), t($stats{'Connections'})
1180
1181__ Created Temp ________________________________________________________
1182Disk table  @>>>>>>>>  @>>>>>/s
1183make_short($stats{'Created_tmp_disk_tables'}), t($stats{'Created_tmp_disk_tables'})
1184Table       @>>>>>>>>  @>>>>>/s    Size: @>>>>>
1185make_short($stats{'Created_tmp_tables'}), t($stats{'Created_tmp_tables'}), make_short($vars{'tmp_table_size'}, 1, 1)
1186File        @>>>>>>>>  @>>>>>/s
1187make_short($stats{'Created_tmp_files'}), t($stats{'Created_tmp_files'})
1188.
1189
1190format TAB =
1191
1192__ Threads _____________________________________________________________
1193Running     @>>>>>>>> of @>>>
1194$stats{'Threads_running'}, $stats{'Threads_connected'}
1195Cached      @>>>>>>>> of @>>>      %Hit: @>>>>>
1196$stats{'Threads_cached'}, $vars{'thread_cache_size'}, make_short(100 - perc($stats{'Threads_created'}, $stats{'Connections'}))
1197Created     @>>>>>>>>  @>>>>>/s
1198make_short($stats{'Threads_created'}), t($stats{'Threads_created'})
1199Slow        @>>>>>>>>  @>>>>>/s
1200$stats{'Slow_launch_threads'}, t($stats{'Slow_launch_threads'})
1201
1202__ Aborted _____________________________________________________________
1203Clients     @>>>>>>>>  @>>>>>/s
1204make_short($stats{'Aborted_clients'}), t($stats{'Aborted_clients'})
1205Connects    @>>>>>>>>  @>>>>>/s
1206make_short($stats{'Aborted_connects'}), t($stats{'Aborted_connects'})
1207
1208__ Bytes _______________________________________________________________
1209Sent        @>>>>>>>>  @>>>>>/s
1210make_short($stats{'Bytes_sent'}), t($stats{'Bytes_sent'})
1211Received    @>>>>>>>>  @>>>>>/s
1212make_short($stats{'Bytes_received'}), t($stats{'Bytes_received'})
1213.
1214
1215format IB =
1216
1217__ InnoDB Buffer Pool __________________________________________________
1218Usage         @>>>>>> of @>>>>>>  %Used: @>>>>>
1219make_short($ib_bp_used, 1), make_short($ib_bp_total, 1), perc($ib_bp_used, $ib_bp_total)
1220Read hit      @>>>>>%
1221$ib_bp_read_ratio;
1222Pages
1223  Free      @>>>>>>>>            %Total: @>>>>>
1224make_short($stats{'Innodb_buffer_pool_pages_free'}), perc($stats{'Innodb_buffer_pool_pages_free'}, $stats{'Innodb_buffer_pool_pages_total'})
1225  Data      @>>>>>>>>                    @>>>>> %Drty: @>>>>>
1226make_short($stats{'Innodb_buffer_pool_pages_data'}), perc($stats{'Innodb_buffer_pool_pages_data'}, $stats{'Innodb_buffer_pool_pages_total'}), perc($stats{'Innodb_buffer_pool_pages_dirty'}, $stats{'Innodb_buffer_pool_pages_data'})
1227  Misc      @>>>>>>>>                    @>>>>>
1228  $stats{'Innodb_buffer_pool_pages_misc'}, perc($stats{'Innodb_buffer_pool_pages_misc'}, $stats{'Innodb_buffer_pool_pages_total'})
1229  Latched   @>>>>>>>>                    @>>>>>
1230$stats{'Innodb_buffer_pool_pages_latched'}, perc($stats{'Innodb_buffer_pool_pages_latched'}, $stats{'Innodb_buffer_pool_pages_total'})
1231Reads       @>>>>>>>>  @>>>>>/s 
1232make_short($stats{'Innodb_buffer_pool_read_requests'}), t($stats{'Innodb_buffer_pool_read_requests'})
1233  From file @>>>>>>>>  @>>>>>/s          @>>>>>
1234make_short($stats{'Innodb_buffer_pool_reads'}), t($stats{'Innodb_buffer_pool_reads'}), perc($stats{'Innodb_buffer_pool_reads'}, $stats{'Innodb_buffer_pool_read_requests'})
1235  Ahead Rnd @>>>>>>>>  @>>>>>/s
1236$stats{'Innodb_buffer_pool_read_ahead_rnd'}, t($stats{'Innodb_buffer_pool_read_ahead_rnd'})
1237  Ahead Sql @>>>>>>>>  @>>>>>/s
1238$stats{'Innodb_buffer_pool_read_ahead_seq'}, t($stats{'Innodb_buffer_pool_read_ahead_seq'})
1239Writes      @>>>>>>>>  @>>>>>/s
1240make_short($stats{'Innodb_buffer_pool_write_requests'}), t($stats{'Innodb_buffer_pool_write_requests'})
1241Flushes     @>>>>>>>>  @>>>>>/s
1242make_short($stats{'Innodb_buffer_pool_pages_flushed'}), t($stats{'Innodb_buffer_pool_pages_flushed'})
1243Wait Free   @>>>>>>>>  @>>>>>/s
1244$stats{'Innodb_buffer_pool_wait_free'}, t($stats{'Innodb_buffer_pool_wait_free'})
1245.
1246
1247format IB_LOCK =
1248
1249__ InnoDB Lock _________________________________________________________
1250Waits       @>>>>>>>>  @>>>>>/s
1251$stats{'Innodb_row_lock_waits'}, t($stats{'Innodb_row_lock_waits'})
1252Current     @>>>>>>>>
1253$stats{'Innodb_row_lock_current_waits'}
1254Time acquiring
1255  Total     @>>>>>>>> ms
1256$stats{'Innodb_row_lock_time'}
1257  Average   @>>>>>>>> ms
1258$stats{'Innodb_row_lock_time_avg'}
1259  Max       @>>>>>>>> ms
1260$stats{'Innodb_row_lock_time_max'}
1261.
1262
1263format IB_DPR =
1264
1265__ InnoDB Data, Pages, Rows ____________________________________________
1266Data
1267  Reads     @>>>>>>>>  @>>>>>/s
1268make_short($stats{'Innodb_data_reads'}), t($stats{'Innodb_data_reads'})
1269  Writes    @>>>>>>>>  @>>>>>/s
1270make_short($stats{'Innodb_data_writes'}), t($stats{'Innodb_data_writes'})
1271  fsync     @>>>>>>>>  @>>>>>/s
1272make_short($stats{'Innodb_data_fsyncs'}), t($stats{'Innodb_data_fsyncs'})
1273  Pending
1274    Reads   @>>>>>>>>
1275$stats{'Innodb_data_pending_reads'}, t($stats{'Innodb_data_pending_reads'})
1276    Writes  @>>>>>>>>
1277$stats{'Innodb_data_pending_writes'}, t($stats{'Innodb_data_pending_writes'})
1278    fsync   @>>>>>>>>
1279$stats{'Innodb_data_pending_fsyncs'}, t($stats{'Innodb_data_pending_fsyncs'})
1280
1281Pages
1282  Created   @>>>>>>>>  @>>>>>/s
1283make_short($stats{'Innodb_pages_created'}), t($stats{'Innodb_pages_created'})
1284  Read      @>>>>>>>>  @>>>>>/s
1285make_short($stats{'Innodb_pages_read'}), t($stats{'Innodb_pages_read'})
1286  Written   @>>>>>>>>  @>>>>>/s
1287make_short($stats{'Innodb_pages_written'}), t($stats{'Innodb_pages_written'})
1288
1289Rows
1290  Deleted   @>>>>>>>>  @>>>>>/s
1291make_short($stats{'Innodb_rows_deleted'}), t($stats{'Innodb_rows_deleted'})
1292  Inserted  @>>>>>>>>  @>>>>>/s
1293make_short($stats{'Innodb_rows_inserted'}), t($stats{'Innodb_rows_inserted'})
1294  Read      @>>>>>>>>  @>>>>>/s
1295make_short($stats{'Innodb_rows_read'}), t($stats{'Innodb_rows_read'})
1296  Updated   @>>>>>>>>  @>>>>>/s
1297make_short($stats{'Innodb_rows_updated'}), t($stats{'Innodb_rows_updated'})
1298.
Note: See TracBrowser for help on using the repository browser.