mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 02:46:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1595 lines
		
	
	
	
		
			49 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			1595 lines
		
	
	
	
		
			49 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/perl
 | |
| 
 | |
| # mariadb-report v4.0 Oct 23 2015
 | |
| # renamed to from mysqlreport in 2020
 | |
| # http://hackmysql.com/mysqlreport
 | |
| 
 | |
| # mariadb-report makes an easy-to-read report of important MySQL/MariaDB status values.
 | |
| # Copyright 2006-2008 Daniel Nichter
 | |
| # Copyright 2012-2015 Jean Weisbuch
 | |
| #
 | |
| # This program is free software; you can redistribute it and/or
 | |
| # modify it under the terms of the GNU General Public License
 | |
| # as published by the Free Software Foundation; either version 2
 | |
| # of the License, or (at your option) any later version.
 | |
| #
 | |
| # This program is distributed in the hope that it will be useful,
 | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| # GNU General Public License for more details.
 | |
| #
 | |
| # The GNU General Public License is available at:
 | |
| # http://www.gnu.org/copyleft/gpl.html
 | |
| 
 | |
| use strict;
 | |
| use File::Temp qw(tempfile);
 | |
| use DBI;
 | |
| use Getopt::Long;
 | |
| eval { require Term::ReadKey; };
 | |
| my $RK = ($@ ? 0 : 1);
 | |
| 
 | |
| sub have_op;
 | |
| 
 | |
| my $WIN = ($^O eq 'MSWin32' ? 1 : 0);
 | |
| my %op;
 | |
| my %mycnf; # ~/.my.cnf
 | |
| my ($tmpfile_fh, $tmpfile);
 | |
| my ($stat_name, $stat_val, $stat_label);
 | |
| my $MySQL_version;
 | |
| my (%stats, %vars); # SHOW STATUS, SHOW VARIABLES
 | |
| my (%DMS_vals, %Com_vals, %ib_vals);
 | |
| my $dbh;
 | |
| my ($questions, $key_read_ratio, $key_write_ratio, $dms, $slow_query_t);
 | |
| my ($key_cache_block_size, $key_buffer_used, $key_buffer_usage);
 | |
| my ($qc_mem_used, $qc_hi_r, $qc_ip_r); # Query Cache
 | |
| my ($ib_bp_used, $ib_bp_total, $ib_bp_read_ratio);
 | |
| my ($relative_live, $relative_infiles);
 | |
| my $real_uptime;
 | |
| my (%stats_present, %stats_past); # For relative reports
 | |
| my ($pagecache_read_ratio, $pagecache_write_ratio, $pagecache_block_size, $pagecache_buffer_used, $pagecache_buffer_usage); # AriaDB pagecache stats
 | |
| my ($binlog_cache_ratio, $binlog_stmt_cache_ratio); # binary log cache
 | |
| my $dbms;
 | |
| my ($rows, $rows_using_indexes);
 | |
| 
 | |
| GetOptions (
 | |
|    \%op,
 | |
|    "user=s",
 | |
|    "password:s",
 | |
|    "host=s",
 | |
|    "port=s",
 | |
|    "socket=s",
 | |
|    "no-mycnf",
 | |
|    "infile|in=s",
 | |
|    "outfile=s",
 | |
|    "flush-status",
 | |
|    "email=s",
 | |
|    "r|relative:i",
 | |
|    "c|report-count=i",
 | |
|    "detach",
 | |
|    "help|?",
 | |
|    "debug"
 | |
| );
 | |
| 
 | |
| show_help_and_exit() if $op{'help'};
 | |
| 
 | |
| get_user_mycnf() unless $op{'no-mycnf'};
 | |
| 
 | |
| # Command line options override ~/.my.cnf
 | |
| $mycnf{'host'}   = $op{'host'}   if have_op 'host';
 | |
| $mycnf{'port'}   = $op{'port'}   if have_op 'port';
 | |
| $mycnf{'socket'} = $op{'socket'} if have_op 'socket';
 | |
| $mycnf{'user'}   = $op{'user'}   if have_op 'user';
 | |
| 
 | |
| $mycnf{'user'} ||= $ENV{'USER'};
 | |
| 
 | |
| if(exists $op{'password'})
 | |
| {
 | |
|    if($op{'password'} eq '') # Prompt for password
 | |
|    {
 | |
|       Term::ReadKey::ReadMode(2) if $RK;
 | |
|       print "Password for database user $mycnf{'user'}: ";
 | |
|       chomp($mycnf{'pass'} = <STDIN>);
 | |
|       Term::ReadKey::ReadMode(0), print "\n" if $RK;
 | |
|    }
 | |
|    else { $mycnf{'pass'} = $op{'password'}; } # Use password given on command line
 | |
| }
 | |
| 
 | |
| $op{'com'} ||= 3;
 | |
| $op{'c'}   ||= 1; # Used in collect_reports() if --r given integer value
 | |
| 
 | |
| $relative_live    = 0;
 | |
| $relative_infiles = 0;
 | |
| 
 | |
| if(defined $op{'r'})
 | |
| {
 | |
|    if($op{r}) { $relative_live    = 1; }  # if -r was given an integer value
 | |
|    else       { $relative_infiles = 1; }
 | |
| }
 | |
| 
 | |
| # The report is written to a tmp file first.
 | |
| # Later it will be moved to $op{'outfile'} or emailed $op{'email'} if needed.
 | |
| ($tmpfile_fh, $tmpfile) = tempfile() or die "Cannot open temporary file for writing: $!\n";
 | |
| 
 | |
| if($op{'detach'})
 | |
| {
 | |
|    $SIG{'TERM'} = 'sig_handler';
 | |
| 
 | |
|    if(fork())
 | |
|    {
 | |
|       print "mariadb-report has forked and detached.\n";
 | |
|       print "While running detached, mariadb-report writes reports to '$tmpfile'.\n";
 | |
| 
 | |
|       exit;
 | |
|    }
 | |
| 
 | |
|    open(STDIN, "</dev/null");
 | |
|    open(STDOUT, "> $tmpfile") or die "Cannot dup STDOUT: $!\n";
 | |
|    open(STDERR, "> $tmpfile") or die "Cannot dup STDERR: $!\n";
 | |
| }
 | |
| 
 | |
| select $tmpfile_fh;
 | |
| $| = 1 if ($op{'detach'} || $relative_live);
 | |
| 
 | |
| print "tmp file: $tmpfile\n" if $op{debug};
 | |
| 
 | |
| # Connect to MySQL/MariaDB
 | |
| if(!$op{'infile'} && !$relative_infiles)
 | |
| {
 | |
|    connect_to_MySQL();
 | |
| }
 | |
| 
 | |
| my $have_innodb_vals = 1; # This might be set to 0 later in get_MySQL_version()
 | |
| my $have_aria_vals = 0;
 | |
| my $have_subquerycache_vals = 0;
 | |
| my $have_binlog_vals = 0;
 | |
| my $use_thread_pool = 0;
 | |
| 
 | |
| if(defined $op{'r'})
 | |
| {
 | |
|    if($relative_live)
 | |
|    {
 | |
|       print STDERR "mariadb-report is writing relative reports to '$tmpfile'.\n" unless $op{'detach'};
 | |
|       get_MySQL_version();
 | |
|       collect_reports();
 | |
|    }
 | |
| 
 | |
|    if($relative_infiles) { read_relative_infiles(); }
 | |
| }
 | |
| else
 | |
| {
 | |
|    if(!$op{'infile'})
 | |
|    {
 | |
|       get_MySQL_version();
 | |
|       get_vals();
 | |
|       get_vars();
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       read_infile($op{'infile'});
 | |
|    }
 | |
| 
 | |
|    get_Com_values();
 | |
| 
 | |
|    set_myisam_vals();
 | |
|    set_ib_vals() if $have_innodb_vals;
 | |
|    set_aria_vals() if $have_aria_vals;
 | |
|    set_subquerycache_vals() if $have_subquerycache_vals;
 | |
|    set_binlog_vals() if $have_binlog_vals;
 | |
| 
 | |
|    write_report();
 | |
| }
 | |
| 
 | |
| exit_tasks_and_cleanup();
 | |
| 
 | |
| exit;
 | |
| 
 | |
| #
 | |
| # Subroutines
 | |
| #
 | |
| sub show_help_and_exit
 | |
| {
 | |
|    print <<"HELP";
 | |
| mariadb-report v4.0 Oct 23 2015
 | |
| mariadb-report makes an easy-to-read report of important MySQL/MariaDB status values.
 | |
| 
 | |
| Command line options (abbreviations work):
 | |
|    --user USER       Connect to MySQL as USER
 | |
|    --password PASS   Use PASS or prompt for MySQL user's password
 | |
|    --host ADDRESS    Connect to MySQL at ADDRESS
 | |
|    --port PORT       Connect to MySQL at PORT
 | |
|    --socket SOCKET   Connect to MySQL at SOCKET
 | |
|    --no-mycnf        Don't read ~/.my.cnf
 | |
|    --infile FILE     Read status values from FILE instead of MySQL
 | |
|    --outfile FILE    Write report to FILE
 | |
|    --email ADDRESS   Email report to ADDRESS (doesn't work on Windows)
 | |
|    --flush-status    Issue FLUSH STATUS; after getting current values
 | |
|    --relative X      Generate relative reports. If X is an integer,
 | |
|                      reports are live from the MySQL server X seconds apart.
 | |
|                      If X is a list of infiles (file1 file2 etc.),
 | |
|                      reports are generated from the infiles in the order
 | |
|                      that they are given.
 | |
|    --report-count N  Collect N number of live relative reports (default 1)
 | |
|    --detach          Fork and detach from terminal (run in background)
 | |
|    --help            Prints this
 | |
|    --debug           Print debugging information
 | |
| 
 | |
| Visit http://hackmysql.com/mysqlreport for more information.
 | |
| HELP
 | |
| 
 | |
|    exit;
 | |
| }
 | |
| 
 | |
| sub get_user_mycnf
 | |
| {
 | |
|    print "get_user_mycnf\n" if $op{debug};
 | |
| 
 | |
|    return if $WIN;
 | |
|    open MYCNF, "$ENV{HOME}/.my.cnf" or return;
 | |
|    while(<MYCNF>)
 | |
|    {
 | |
|       if(/^(.+?)\s*=\s*"?(.+?)"?\s*$/)
 | |
|       {
 | |
|          $mycnf{$1} = $2;
 | |
|          print "get_user_mycnf: read '$1 = $2'\n" if $op{debug};
 | |
|       }
 | |
|    }
 | |
|    $mycnf{'pass'} ||= $mycnf{'password'} if exists $mycnf{'password'};
 | |
|    close MYCNF;
 | |
| }
 | |
| 
 | |
| sub connect_to_MySQL
 | |
| {
 | |
|     print "connect_to_MySQL\n" if $op{debug};
 | |
| 
 | |
|     if(my @driverList = grep {/mariadb|mysql/i} DBI->available_drivers()) {
 | |
|         my $dsn;
 | |
|         my $driver = undef;
 | |
| 
 | |
|         if(grep {/mariadb/i} @driverList)
 | |
|         {
 | |
|             $driver = "DBI:MariaDB";
 | |
|         }
 | |
|         elsif(grep {/mysql/i} @driverList)
 | |
|         {
 | |
|             $driver = "DBI:mysql";
 | |
|         }
 | |
| 
 | |
|         if($mycnf{'socket'} && -S $mycnf{'socket'})
 | |
|         {
 | |
|             if(grep {/mariadb/i} @driverList)
 | |
|             {
 | |
|                 $dsn = $driver . ":mariadb_socket=$mycnf{socket}";
 | |
|             }
 | |
|             elsif(grep {/mysql/i} @driverList)
 | |
|             {
 | |
|                 $dsn = $driver . ":mysql_socket=$mycnf{socket}";
 | |
|             }
 | |
|         }
 | |
|         elsif($mycnf{'host'})
 | |
|         {
 | |
|             $dsn = $driver . ":host=$mycnf{host}" . ($mycnf{port} ? ";port=$mycnf{port}" : "");
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             $dsn = $driver . ":host=localhost";
 | |
|         }
 | |
| 
 | |
|         print "connect_to_MySQL: DBI DSN: " . $dsn . "\n" if $op{debug};
 | |
| 
 | |
|         $dbh = DBI->connect($dsn, $mycnf{'user'}, $mycnf{'pass'}) or die;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         print STDERR "Install Perl 5.x driver: DBD:mysql or DBD:MariaDB\n";
 | |
|         print STDERR "currently installed Perl DBD drivers:\n";
 | |
|         foreach my $driver (DBI->available_drivers())
 | |
|         {
 | |
|             print STDERR " * " . $driver . "\n";
 | |
|         }
 | |
|         print STDERR "\n";
 | |
|         die("Exit as no MariaDB DBI driver found!\n");
 | |
|     }
 | |
| }
 | |
| 
 | |
| sub collect_reports
 | |
| {
 | |
|    print "collect_reports\n" if $op{debug};
 | |
| 
 | |
|    my $i;
 | |
| 
 | |
|    get_vals();
 | |
|    get_vars();
 | |
| 
 | |
|    get_Com_values();
 | |
| 
 | |
|    %stats_past = %stats;
 | |
| 
 | |
|    set_myisam_vals();
 | |
|    set_ib_vals() if $have_innodb_vals;
 | |
|    set_aria_vals() if $have_aria_vals;
 | |
|    set_subquerycache_vals() if $have_subquerycache_vals;
 | |
|    set_binlog_vals() if $have_binlog_vals;
 | |
| 
 | |
|    print "#\n# Beginning report, 0 0:0:0\n#\n";
 | |
| 
 | |
|    write_report();
 | |
| 
 | |
|    for($i = 0; $i < $op{'c'}; $i++)
 | |
|    {
 | |
|       $dbh->disconnect();
 | |
| 
 | |
|       sleep($op{'r'});
 | |
| 
 | |
|       connect_to_MySQL();
 | |
| 
 | |
|       print "\n#\n# Interval report " , $i + 1 , ", +", sec_to_dhms(($i + 1) * $op{'r'}), "\n#\n";
 | |
| 
 | |
|       get_vals();
 | |
| 
 | |
|       write_relative_report();
 | |
|    }
 | |
| }
 | |
| 
 | |
| sub read_relative_infiles
 | |
| {
 | |
|    print "read_relative_infiles\n" if $op{debug};
 | |
| 
 | |
|    my $slurp;    # Used to check infiles for multiple sets of status values
 | |
|    my $n_stats;  # Number of multiple sets of status values in an infile
 | |
|    my $infile;
 | |
|    my $report_n; # Report number
 | |
| 
 | |
|    $report_n = 1;
 | |
| 
 | |
|    foreach $infile (@ARGV)
 | |
|    {
 | |
|       # Read all of infile into $slurp
 | |
|       open INFILE, "< $infile" or warn and next;
 | |
|       $slurp = do { local $/;  <INFILE> };
 | |
|       close INFILE;
 | |
| 
 | |
|       $n_stats = 0;
 | |
| 
 | |
|       # Count number of status value sets
 | |
|       $n_stats++ while $slurp =~ /Aborted_clients/g;
 | |
| 
 | |
|       print "read_relative_infiles: found $n_stats sets of status values in file '$infile'\n"
 | |
|          if $op{debug};
 | |
| 
 | |
|       if($n_stats == 1)
 | |
|       {
 | |
|          read_infile($infile);
 | |
|          relative_infile_report($report_n++);
 | |
|       }
 | |
| 
 | |
|       if($n_stats > 1)
 | |
|       {
 | |
|          my @tmpfile_fh;
 | |
|          my @tmpfile_name;
 | |
|          my $i;
 | |
|          my $stat_n;  # Status value set number
 | |
| 
 | |
|          # Create a tmp file for each set of status values
 | |
|          for($i = 0; $i < $n_stats; $i++)
 | |
|          {
 | |
|             my ($fh, $name) = tempfile()
 | |
|                or die "read_relative_infiles: cannot open temporary file for writing: $!\n";
 | |
| 
 | |
|             push(@tmpfile_fh, $fh);
 | |
|             push(@tmpfile_name, $name);
 | |
| 
 | |
|             print "read_relative_infiles: created tmp file '$name' for set $i\n" if $op{debug};
 | |
|          }
 | |
| 
 | |
|          $i = 0;
 | |
|          $stat_n = 0;
 | |
| 
 | |
|          select $tmpfile_fh[$i];
 | |
| 
 | |
|          # Read infile again and copy each set of status values to separate tmp files
 | |
|          open INFILE, "< $infile" or warn and next;
 | |
|          while(<INFILE>)
 | |
|          {
 | |
|             next if /^\+/;
 | |
|             next if /^$/;
 | |
| 
 | |
|             # The infile must begin with the system variable values.
 | |
|             # Therefore, the first occurrence of Aborted_clients indicates the beginning
 | |
|             # of the first set of status values if no sets have occurred yet ($stat_n == 0).
 | |
|             # In this case, the following status values are printed to the current fh,
 | |
|             # along with the system variable values read thus far, until Aborted_clients
 | |
|             # occurs again. Then begins the second and subsequent sets of status values.
 | |
| 
 | |
|             if(/Aborted_clients/)
 | |
|             {
 | |
|                print and next if $stat_n++ == 0;
 | |
|                select $tmpfile_fh[++$i];
 | |
|             }
 | |
| 
 | |
|             print;
 | |
|          }
 | |
|          close INFILE;
 | |
| 
 | |
|          # Re-select the main tmp file into which the reports are being written.
 | |
|          select $tmpfile_fh;
 | |
| 
 | |
|          for($i = 0; $i < $n_stats; $i++)
 | |
|          {
 | |
|             close $tmpfile_fh[$i];
 | |
| 
 | |
|             print "read_relative_infiles: reading set $i tmp file '$tmpfile_name[$i]'\n"
 | |
|                if $op{debug};
 | |
| 
 | |
|             read_infile($tmpfile_name[$i]);
 | |
|             relative_infile_report($report_n++);
 | |
| 
 | |
|             if($WIN) { `del $tmpfile_name[$i]`;   }
 | |
|             else     { `rm -f $tmpfile_name[$i]`; }
 | |
| 
 | |
|             print "read_relative_infiles: deleted set $i tmp file '$tmpfile_name[$i]'\n"
 | |
|                if $op{debug};
 | |
|          }
 | |
| 
 | |
|       } # if($n_stats > 1)
 | |
|    } # foreach $infile (@files)
 | |
| }
 | |
| 
 | |
| sub relative_infile_report
 | |
| {
 | |
|    print "relative_infile_report\n" if $op{debug};
 | |
| 
 | |
|    my $report_n = shift;
 | |
| 
 | |
|    if($report_n == 1)
 | |
|    {
 | |
|       get_Com_values();
 | |
| 
 | |
|       %stats_past = %stats;
 | |
| 
 | |
|       set_myisam_vals();
 | |
|       set_ib_vals() if $have_innodb_vals;
 | |
|       set_aria_vals() if $have_aria_vals;
 | |
|       set_subquerycache_vals() if $have_subquerycache_vals;
 | |
|       set_binlog_vals() if $have_binlog_vals;
 | |
| 
 | |
|       print "#\n# Beginning report, 0 0:0:0\n#\n";
 | |
| 
 | |
|       write_report();
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       print "\n#\n# Interval report ", $report_n - 1, ", +",
 | |
|          sec_to_dhms($stats{Uptime} - $stats_past{Uptime}),
 | |
|          "\n#\n";
 | |
| 
 | |
|       write_relative_report();
 | |
|    }
 | |
| }
 | |
| 
 | |
| sub get_vals
 | |
| {
 | |
|    print "get_vals\n" if $op{debug};
 | |
| 
 | |
|    my (@row, $query);
 | |
| 
 | |
|    # Get status values
 | |
|    if($MySQL_version >= 50002)
 | |
|    {
 | |
|       $query = $dbh->prepare("SHOW GLOBAL STATUS;");
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       $query = $dbh->prepare("SHOW STATUS;");
 | |
|    }
 | |
|    $query->execute();
 | |
|    # To avoid problems if the variable capitalization would change (eg. TokuDB on MariaDB 5.5 => 10.0), the $stats index is forced to have its first char uppercase and the rest lowercase
 | |
|    while(@row = $query->fetchrow_array()) { $stats{ucfirst(lc($row[0]))} = $row[1]; }
 | |
|    $query->finish();
 | |
| 
 | |
|    $real_uptime = $stats{'Uptime'};
 | |
| }
 | |
| 
 | |
| sub get_vars
 | |
| {
 | |
|    print "get_vars\n" if $op{debug};
 | |
| 
 | |
|    my (@row, $query);
 | |
| 
 | |
|    # Get server system variables
 | |
|    $query = $dbh->prepare("SHOW VARIABLES;");
 | |
|    $query->execute();
 | |
|    while(@row = $query->fetchrow_array()) { $vars{$row[0]} = $row[1]; }
 | |
|    $query->finish();
 | |
|    # table_cache was renamed to table_open_cache in MySQL 5.1.3
 | |
|    if($MySQL_version >= 50103)
 | |
|    {
 | |
|       $vars{'table_cache'} = $vars{'table_open_cache'};
 | |
|    }
 | |
|    # log_slow_queries was renamed to slow_query_log in MySQL 5.1.29
 | |
|    if($MySQL_version >= 50129)
 | |
|    {
 | |
|       $vars{'log_slow_queries'} = $vars{'slow_query_log'};
 | |
|    }
 | |
| }
 | |
| 
 | |
| sub read_infile
 | |
| {
 | |
|    print "read_infile\n" if $op{debug};
 | |
| 
 | |
|    my $infile = shift;
 | |
| 
 | |
|    # Default required system variable values if not set in INFILE.
 | |
|    # As of mysqlreport v3.5 the direct output from SHOW VARIABLES;
 | |
|    # can be put into INFILE instead. See http://hackmysql.com/mysqlreportdoc
 | |
|    # for details.
 | |
|    $vars{'version'} = "0.0.0"         if !exists $vars{'version'};
 | |
|    $vars{'table_cache'} = 64          if !exists $vars{'table_cache'};
 | |
|    $vars{'max_connections'} = 100     if !exists $vars{'max_connections'};
 | |
|    $vars{'key_buffer_size'} = 8388600 if !exists $vars{'key_buffer_size'}; # 8M
 | |
|    $vars{'thread_cache_size'} = 0     if !exists $vars{'thread_cache_size'};
 | |
|    $vars{'tmp_table_size'} = 0        if !exists $vars{'tmp_table_size'};
 | |
|    $vars{'long_query_time'} = '?'     if !exists $vars{'long_query_time'};
 | |
|    $vars{'log_slow_queries'} = '?'    if !exists $vars{'log_slow_queries'};
 | |
| 
 | |
|    # One should also add:
 | |
|    #    key_cache_block_size
 | |
|    #    query_cache_size
 | |
|    # to INFILE if needed.
 | |
| 
 | |
|    open INFILE, "< $infile" or die "Cannot open INFILE '$infile': $!\n";
 | |
| 
 | |
|    while(<INFILE>)
 | |
|    {
 | |
|       last if !defined $_;
 | |
| 
 | |
|       next if /^\+/;  # skip divider lines
 | |
|       next if /^$/;   # skip blank lines
 | |
| 
 | |
|       next until /(Aborted_clients|back_log|=)/;
 | |
| 
 | |
|       if($1 eq 'Aborted_clients')  # status values
 | |
|       {
 | |
|          print "read_infile: start stats\n" if $op{debug};
 | |
| 
 | |
|          while($_)
 | |
|          {
 | |
|             chomp;
 | |
|             if(/([A-Za-z_]+)[\s\t|]+(\d+)/)
 | |
|             {
 | |
|                $stats{$1} = $2;
 | |
|                print "read_infile: save $1 = $2\n" if $op{debug};
 | |
|             }
 | |
|             else { print "read_infile: ignore '$_'\n" if $op{debug}; }
 | |
| 
 | |
|             last if $1 eq 'Uptime';  # exit while() if end of status values
 | |
|             $_ = <INFILE>;  # otherwise, read next line of status values
 | |
|          }
 | |
|       }
 | |
|       elsif($1 eq 'back_log')  # system variable values
 | |
|       {
 | |
|          print "read_infile: start vars\n" if $op{debug};
 | |
| 
 | |
|          while($_)
 | |
|          {
 | |
|             chomp;
 | |
|             if(/([A-Za-z_]+)[\s\t|]+([\w\.\-]+)/)  # This will exclude some vars
 | |
|             {                                      # like pid_file which we don't need
 | |
|                $vars{$1} = $2;
 | |
|                print "read_infile: save $1 = $2\n" if $op{debug};
 | |
|             }
 | |
|             else { print "read_infile: ignore '$_'\n" if $op{debug}; }
 | |
| 
 | |
|             last if $1 eq 'wait_timeout';  # exit while() if end of vars
 | |
|             $_ = <INFILE>;  # otherwise, read next line of vars
 | |
|          }
 | |
|       }
 | |
|       elsif($1 eq '=')  # old style, manually added system variable values
 | |
|       {
 | |
|          print "read_infile: start old vars\n" if $op{debug};
 | |
| 
 | |
|          while($_ && $_ =~ /=/)
 | |
|          {
 | |
|             chomp;
 | |
|             if(/^\s*(\w+)\s*=\s*([0-9.]+)(M*)\s*$/)  # e.g.: key_buffer_size = 128M
 | |
|             {
 | |
|                $vars{$1} = ($3 ? $2 * 1024 * 1024 : $2);
 | |
|                print "read_infile: read '$_' as $1 = $vars{$1}\n" if $op{debug};
 | |
|             }
 | |
|             else { print "read_infile: ignore '$_'\n" if $op{debug}; }
 | |
| 
 | |
|             $_ = <INFILE>;  # otherwise, read next line of old vars
 | |
|          }
 | |
| 
 | |
|          redo;
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          print "read_infile: unrecognized line: '$_'\n" if $op{debug};
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    close INFILE;
 | |
| 
 | |
|    $real_uptime = $stats{'Uptime'};
 | |
| 
 | |
|    $vars{'table_cache'} = $vars{'table_open_cache'} if exists $vars{'table_open_cache'};
 | |
| 
 | |
|    get_MySQL_version();
 | |
| }
 | |
| 
 | |
| sub get_MySQL_version
 | |
| {
 | |
|    print "get_MySQL_version\n" if $op{debug};
 | |
| 
 | |
|    return if $MySQL_version;
 | |
| 
 | |
|    my ($major, $minor, $patch);
 | |
| 
 | |
|    if($op{'infile'} || $relative_infiles)
 | |
|    {
 | |
|       ($major, $minor, $patch) = ($vars{'version'} =~ /^(\d{1,2})\.(\d{1,2})\.(\d{1,2})/);
 | |
|       if($vars{'version'} =~ /^\d{1,2}\.\d{1,2}\.\d{1,2}-MariaDB/) {
 | |
|         print "MariaDB detected\n" if $op{debug};
 | |
|         $dbms = "MariaDB";
 | |
|       } else {
 | |
|         $dbms = "MySQL";
 | |
|       }
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       my (@row, $query);
 | |
| 
 | |
|       $query = $dbh->prepare("SHOW VARIABLES LIKE 'version';");
 | |
|       $query->execute();
 | |
|       @row = $query->fetchrow_array();
 | |
|       $query->finish();
 | |
|       ($major, $minor, $patch) = ($row[1] =~ /^(\d{1,2})\.(\d{1,2})\.(\d{1,2})/);
 | |
|       if($row[1] =~ /^\d{1,2}\.\d{1,2}\.\d{1,2}-MariaDB/)
 | |
|       {
 | |
|          print "MariaDB detected\n" if $op{debug};
 | |
|          $dbms = "MariaDB";
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|          $dbms = "MySQL";
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    # The major version number is kept as is while the minor version and the revision number are forced to 2 digits
 | |
|    # e.g.: 5.5.9 will be 50509, 10.0.5 will be 100005 and 10.1.23 will be 100123
 | |
|    $MySQL_version = sprintf("%d%02d%02d", $major, $minor, $patch);
 | |
|    print "Version $MySQL_version\n" if $op{debug};
 | |
| 
 | |
|    # Innodb_ status values were added in 5.0.2
 | |
|    if($MySQL_version < 50002)
 | |
|    {
 | |
|       $have_innodb_vals = 0;
 | |
|       print "get_MySQL_version: no InnoDB reports because MySQL version is older than 5.0.2\n" if $op{debug};
 | |
|    } else {
 | |
|       $have_innodb_vals = $dbh->selectall_arrayref("SELECT SUPPORT FROM information_schema.engines WHERE ENGINE = 'InnoDB';", undef)->[0][0];
 | |
|       if(defined($have_innodb_vals) && ($have_innodb_vals eq "YES" || $have_innodb_vals eq "DEFAULT"))
 | |
|       {
 | |
|          print "InnoDB detected\n" if $op{debug};
 | |
|          $have_innodb_vals = 1;
 | |
|       } else {
 | |
|          print "InnoDB is not activated\n" if $op{debug};
 | |
|          $have_innodb_vals = 0;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if($dbms eq "MariaDB") {
 | |
|       $have_aria_vals = $dbh->selectall_arrayref("SELECT SUPPORT FROM information_schema.engines WHERE ENGINE = 'Aria';", undef)->[0][0];
 | |
|       if(defined($have_aria_vals) && $have_aria_vals eq "YES")
 | |
|       {
 | |
|          print "Aria engine detected\n" if $op{debug};
 | |
|          $have_aria_vals = 1;
 | |
|       } else {
 | |
|          $have_aria_vals = 0;
 | |
|       }
 | |
| 
 | |
|       # MariaDB 5.3+, activated by default since 5.3.2
 | |
|       $have_subquerycache_vals = $dbh->selectall_arrayref("SELECT VARIABLE_VALUE REGEXP ',subquery_cache=on,|^subquery_cache=on,|,subquery_cache=on\$' AS SUBQUERY_CACHE FROM information_schema.global_variables WHERE VARIABLE_NAME = 'optimizer_switch';", undef)->[0][0];
 | |
|       if(defined($have_subquerycache_vals) && $have_subquerycache_vals eq "1")
 | |
|       {
 | |
|          print "Subquery cache is activated\n" if $op{debug};
 | |
|          $have_subquerycache_vals = 1;
 | |
|       } else {
 | |
|          $have_subquerycache_vals = 0;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    if($MySQL_version >= 50000)
 | |
|    {
 | |
|       # These checks use the 'information_schema' virtual database that has been added on MySQL 5.0
 | |
| 
 | |
|       # MariaDB 5.5.21+ and Percona Server 5.5.30+ use the same thread pool implementation
 | |
|       $use_thread_pool = $dbh->selectall_arrayref("SELECT VARIABLE_VALUE FROM information_schema.global_variables WHERE VARIABLE_NAME = 'thread_handling';", undef)->[0][0];
 | |
|       if(defined($use_thread_pool) && $use_thread_pool eq "pool-of-threads") {
 | |
|          print "Thread pool is used\n" if $op{debug};
 | |
|          $use_thread_pool = 1;
 | |
|       } else {
 | |
|          $use_thread_pool = 0;
 | |
|       }
 | |
| 
 | |
|       $have_binlog_vals = $dbh->selectall_arrayref("SELECT VARIABLE_VALUE FROM information_schema.global_variables WHERE VARIABLE_NAME = 'log_bin';", undef)->[0][0];
 | |
|       if(defined($have_binlog_vals) && $have_binlog_vals eq "ON")
 | |
|       {
 | |
|          print "Binary log is activated\n" if $op{debug};
 | |
|          $have_binlog_vals = 1;
 | |
|       } else {
 | |
|          $have_binlog_vals = 0;
 | |
|       }
 | |
|    }
 | |
| }
 | |
| 
 | |
| sub set_myisam_vals
 | |
| {
 | |
|    print "set_myisam_vals\n" if $op{debug};
 | |
| 
 | |
| # should be moved elsewhere
 | |
|    $questions = $stats{'Questions'};
 | |
| 
 | |
|    $key_read_ratio = sprintf "%.2f",
 | |
|                      ($stats{'Key_read_requests'} ?
 | |
|                       100 - ($stats{'Key_reads'} / $stats{'Key_read_requests'}) * 100 :
 | |
|                       0);
 | |
| 
 | |
|    $key_write_ratio = sprintf "%.2f",
 | |
|                       ($stats{'Key_write_requests'} ?
 | |
|                        100 - ($stats{'Key_writes'} / $stats{'Key_write_requests'}) * 100 :
 | |
|                        0);
 | |
| 
 | |
|    $key_cache_block_size = (defined $vars{'key_cache_block_size'} ?
 | |
|                             $vars{'key_cache_block_size'} :
 | |
|                             1024);
 | |
| 
 | |
|    $key_buffer_used = $stats{'Key_blocks_used'} * $key_cache_block_size;
 | |
| 
 | |
|    if(defined $stats{'Key_blocks_unused'}) # MySQL 4.1.2+
 | |
|    {
 | |
|       $key_buffer_usage =  $vars{'key_buffer_size'} -
 | |
|                            ($stats{'Key_blocks_unused'} * $key_cache_block_size);
 | |
|    }
 | |
|    else { $key_buffer_usage = -1; }
 | |
| 
 | |
|    # Data Manipulation Statements: http://dev.mysql.com/doc/refman/5.0/en/data-manipulation.html
 | |
|    %DMS_vals =
 | |
|    (
 | |
|       SELECT  => $stats{'Com_select'},
 | |
|       INSERT  => $stats{'Com_insert'}  + $stats{'Com_insert_select'},
 | |
|       REPLACE => $stats{'Com_replace'} + $stats{'Com_replace_select'},
 | |
|       UPDATE  => $stats{'Com_update'}  +
 | |
|                  (exists $stats{'Com_update_multi'} ? $stats{'Com_update_multi'} : 0),
 | |
|       DELETE  => $stats{'Com_delete'}  +
 | |
|                  (exists $stats{'Com_delete_multi'} ? $stats{'Com_delete_multi'} : 0)
 | |
|    );
 | |
| 
 | |
|    $dms = $DMS_vals{SELECT} + $DMS_vals{INSERT} + $DMS_vals{REPLACE} + $DMS_vals{UPDATE} + $DMS_vals{DELETE};
 | |
| 
 | |
|    $slow_query_t = format_u_time($vars{long_query_time});
 | |
| }
 | |
| 
 | |
| sub set_ib_vals
 | |
| {
 | |
|    print "set_ib_vals\n" if $op{debug};
 | |
| 
 | |
|    $ib_bp_used  = ($stats{'Innodb_buffer_pool_pages_total'} -
 | |
|                    $stats{'Innodb_buffer_pool_pages_free'}) *
 | |
|                    $stats{'Innodb_page_size'};
 | |
| 
 | |
|    $ib_bp_total = $stats{'Innodb_buffer_pool_pages_total'} * $stats{'Innodb_page_size'};
 | |
| 
 | |
|    $ib_bp_read_ratio = sprintf "%.2f",
 | |
|                        ($stats{'Innodb_buffer_pool_read_requests'} ?
 | |
|                         100 - ($stats{'Innodb_buffer_pool_reads'} /
 | |
|                            $stats{'Innodb_buffer_pool_read_requests'}) * 100 :
 | |
|                         0);
 | |
| }
 | |
| 
 | |
| sub set_aria_vals
 | |
| {
 | |
|    print "set_aria_vals\n" if $op{debug};
 | |
| 
 | |
|    $pagecache_read_ratio = sprintf "%.2f",
 | |
|                      ($stats{'Aria_pagecache_read_requests'} ?
 | |
|                       100 - ($stats{'Aria_pagecache_reads'} / $stats{'Aria_pagecache_read_requests'}) * 100 :
 | |
|                       0);
 | |
| 
 | |
|    $pagecache_write_ratio = sprintf "%.2f",
 | |
|                       ($stats{'Aria_pagecache_write_requests'} ?
 | |
|                        100 - ($stats{'Aria_pagecache_writes'} / $stats{'Aria_pagecache_write_requests'}) * 100 :
 | |
|                        0);
 | |
| 
 | |
|    $pagecache_block_size = (defined $vars{'aria_block_size'} ?
 | |
|                             $vars{'aria_block_size'} :
 | |
|                             1024);
 | |
| 
 | |
|    $pagecache_buffer_used = $stats{'Aria_pagecache_blocks_used'} * $pagecache_block_size;
 | |
| 
 | |
|    $pagecache_buffer_usage =  $vars{'aria_pagecache_buffer_size'} -
 | |
|                       ($stats{'Aria_pagecache_blocks_unused'} * $pagecache_block_size);
 | |
| }
 | |
| 
 | |
| sub set_subquerycache_vals
 | |
| {
 | |
|    print "set_subquerycache_vals\n" if $op{debug};
 | |
| }
 | |
| 
 | |
| sub set_binlog_vals
 | |
| {
 | |
|    print "set_binlog_vals\n" if $op{debug};
 | |
| 
 | |
|    if($stats{'Binlog_cache_use'} gt 0) { $binlog_cache_ratio = $stats{'Binlog_cache_disk_use'} / $stats{'Binlog_cache_use'}; }
 | |
|    else { $binlog_cache_ratio = 0; }
 | |
| 
 | |
|    if(defined($stats{'Binlog_stmt_cache_use'}) && $stats{'Binlog_stmt_cache_use'} gt 0) { $binlog_stmt_cache_ratio = $stats{'Binlog_stmt_cache_disk_use'} / $stats{'Binlog_stmt_cache_use'}; }
 | |
|    else { $binlog_stmt_cache_ratio = 0; }
 | |
| }
 | |
| 
 | |
| sub write_relative_report
 | |
| {
 | |
|    print "write_relative_report\n" if $op{debug};
 | |
| 
 | |
|    %stats_present = %stats;
 | |
| 
 | |
|    for(keys %stats)
 | |
|    {
 | |
|       if($stats_past{$_} =~ /\d+/)
 | |
|       {
 | |
|          if($stats_present{$_} >= $stats_past{$_}) # Avoid negative values
 | |
|          {
 | |
|             $stats{$_} = $stats_present{$_} - $stats_past{$_};
 | |
|          }
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    # These values are either "at present" or "high water marks".
 | |
|    # Therefore, it is more logical to not relativize these values.
 | |
|    # Doing otherwise causes strange and misleading values.
 | |
|    $stats{'Key_blocks_used'}      = $stats_present{'Key_blocks_used'};
 | |
|    $stats{'Open_tables'}          = $stats_present{'Open_tables'};
 | |
|    $stats{'Max_used_connections'} = $stats_present{'Max_used_connections'};
 | |
|    $stats{'Threads_running'}      = $stats_present{'Threads_running'};
 | |
|    $stats{'Threads_connected'}    = $stats_present{'Threads_connected'};
 | |
|    $stats{'Threads_cached'}       = $stats_present{'Threads_cached'};
 | |
|    $stats{'Qcache_free_blocks'}   = $stats_present{'Qcache_free_blocks'};
 | |
|    $stats{'Qcache_total_blocks'}  = $stats_present{'Qcache_total_blocks'};
 | |
|    $stats{'Qcache_free_memory'}   = $stats_present{'Qcache_free_memory'};
 | |
|    if($have_innodb_vals)
 | |
|    {
 | |
|       $stats{'Innodb_page_size'}                 = $stats_present{'Innodb_page_size'};
 | |
|       $stats{'Innodb_buffer_pool_pages_data'}    = $stats_present{'Innodb_buffer_pool_pages_data'};
 | |
|       $stats{'Innodb_buffer_pool_pages_dirty'}   = $stats_present{'Innodb_buffer_pool_pages_dirty'};
 | |
|       $stats{'Innodb_buffer_pool_pages_free'}    = $stats_present{'Innodb_buffer_pool_pages_free'};
 | |
|       $stats{'Innodb_buffer_pool_pages_latched'} = $stats_present{'Innodb_buffer_pool_pages_latched'};
 | |
|       $stats{'Innodb_buffer_pool_pages_misc'}    = $stats_present{'Innodb_buffer_pool_pages_misc'};
 | |
|       $stats{'Innodb_buffer_pool_pages_total'}   = $stats_present{'Innodb_buffer_pool_pages_total'};
 | |
|       $stats{'Innodb_data_pending_fsyncs'}       = $stats_present{'Innodb_data_pending_fsyncs'};
 | |
|       $stats{'Innodb_data_pending_reads'}        = $stats_present{'Innodb_data_pending_reads'};
 | |
|       $stats{'Innodb_data_pending_writes'}       = $stats_present{'Innodb_data_pending_writes'};
 | |
| 
 | |
|       # Innodb_row_lock_ values were added in MySQL 5.0.3
 | |
|       if($MySQL_version >= 50003)
 | |
|       {
 | |
|          $stats{'Innodb_row_lock_current_waits'} = $stats_present{'Innodb_row_lock_current_waits'};
 | |
|          $stats{'Innodb_row_lock_time_avg'}      = $stats_present{'Innodb_row_lock_time_avg'};
 | |
|          $stats{'Innodb_row_lock_time_max'}      = $stats_present{'Innodb_row_lock_time_max'};
 | |
|       }
 | |
|    }
 | |
|   if($have_aria_vals)
 | |
|   {
 | |
|      $stats{'Aria_pagecache_blocks_used'} = $stats_present{'Aria_pagecache_blocks_used'};
 | |
|   }
 | |
| 
 | |
|    get_Com_values();
 | |
| 
 | |
|    %stats_past = %stats_present;
 | |
| 
 | |
|    set_myisam_vals();
 | |
|    set_ib_vals() if $have_innodb_vals;
 | |
|    set_aria_vals() if $have_aria_vals;
 | |
|    set_subquerycache_vals() if $have_subquerycache_vals;
 | |
|    set_binlog_vals() if $have_binlog_vals;
 | |
| 
 | |
|    write_report();
 | |
| }
 | |
| 
 | |
| sub write_report
 | |
| {
 | |
|    print "write_report\n" if $op{debug};
 | |
| 
 | |
|    $~ = 'MYSQL_TIME', write;
 | |
|    $~ = 'KEY_BUFF_MAX', write;
 | |
|    if($key_buffer_usage != -1) { $~ = 'KEY_BUFF_USAGE', write }
 | |
|    $~ = 'KEY_RATIOS', write;
 | |
|    write_DTQ();
 | |
|    $~ = 'SLOW_DMS', write;
 | |
|    write_DMS();
 | |
|    write_Com();
 | |
|    write_Rows();
 | |
|    $~ = 'SAS', write;
 | |
|    write_qcache();
 | |
|    $~ = 'REPORT_END', write;
 | |
|    $~ = 'THREADS', write;
 | |
|    if($use_thread_pool)
 | |
|    {
 | |
|       $~ = 'THREADPOOL', write;
 | |
|    } else {
 | |
|       $~ = 'THREADPERCONNECTION', write;
 | |
|    }
 | |
|    $~ = 'TAB', write;
 | |
| 
 | |
|    write_InnoDB() if $have_innodb_vals;
 | |
|    write_Aria() if $have_aria_vals;
 | |
|    write_Subquerycache() if $have_subquerycache_vals;
 | |
|    write_Binlog() if $have_binlog_vals;
 | |
| }
 | |
| 
 | |
| sub sec_to_dhms # Seconds to days+hours:minutes:seconds
 | |
| {
 | |
|    my $s = shift;
 | |
|    my ($d, $h, $m) = (0, 0, 0);
 | |
| 
 | |
|    return '0 0:0:0' if $s <= 0;
 | |
| 
 | |
|    if($s >= 86400)
 | |
|    {
 | |
|       $d = int $s / 86400;
 | |
|       $s -= $d * 86400;
 | |
|    }
 | |
| 
 | |
|    if($s >= 3600)
 | |
|    {
 | |
|      $h = int $s / 3600;
 | |
|      $s -= $h * 3600;
 | |
|    }
 | |
| 
 | |
|    $m = int $s / 60;
 | |
|    $s -= $m * 60;
 | |
| 
 | |
|    return "$d+$h:$m:$s";
 | |
| }
 | |
| 
 | |
| sub make_short
 | |
| {
 | |
|    my ($number, $kb, $d) = @_;
 | |
|    my $n = 0;
 | |
|    my $short;
 | |
| 
 | |
|    $d ||= 2;
 | |
| 
 | |
|    if($kb) { while ($number > 1023) { $number /= 1024; $n++; }; }
 | |
|    else { while ($number > 999) { $number /= 1000; $n++; }; }
 | |
| 
 | |
|    $short = sprintf "%.${d}f%s", $number, ('','k','M','G','T')[$n];
 | |
|    if($short =~ /^(.+)\.(00)$/) { return $1; } # 12.00 -> 12 but not 12.00k -> 12k
 | |
| 
 | |
|    return $short;
 | |
| }
 | |
| 
 | |
| # What began as a simple but great idea has become the new standard:
 | |
| # long_query_time in microseconds. For MySQL 5.1.21+ this is now
 | |
| # standard. For 4.1 and 5.0 patches, the architects of this idea
 | |
| # provide: http://www.mysqlperformanceblog.com/mysql-patches/
 | |
| # Relevant notes in MySQL manual:
 | |
| # http://dev.mysql.com/doc/refman/5.1/en/slow-query-log.html
 | |
| #
 | |
| # The format_u_time sub simply beautifies long_query_time.
 | |
| 
 | |
| sub format_u_time  # format microsecond (µ) time value
 | |
| {
 | |
|    # 0.000000 - 0.000999 = 0 - 999 µ
 | |
|    # 0.001000 - 0.999999 = 1 ms - 999.999 ms
 | |
|    # 1.000000 - n.nnnnnn = 1 s - n.nnnnn s
 | |
| 
 | |
|    my $t = shift;
 | |
|    my $f;  # formatted µ time
 | |
|    my $u = chr(($WIN ? 230 : 181));
 | |
| 
 | |
|    $t = 0 if $t < 0;
 | |
| 
 | |
|    if($t > 0 && $t <= 0.000999)
 | |
|    {
 | |
|       $f = ($t * 1000000) . " $u";
 | |
|    }
 | |
|    elsif($t >= 0.001000 && $t <= 0.999999)
 | |
|    {
 | |
|       $f = ($t * 1000) . ' ms';
 | |
|    }
 | |
|    elsif($t >= 1)
 | |
|    {
 | |
|       $f = ($t * 1) . ' s';  # * 1 to remove insignificant zeros
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       $f = 0;  # $t should = 0 at this point
 | |
|    }
 | |
| 
 | |
|    return $f;
 | |
| }
 | |
| 
 | |
| sub perc # Percentage
 | |
| {
 | |
|    my($is, $of) = @_;
 | |
|    $is = 0 if (not defined $is);
 | |
|    return sprintf "%.2f", ($is * 100) / ($of ||= 1);
 | |
| }
 | |
| 
 | |
| sub t # Time average per second
 | |
| {
 | |
|    my $val = shift;
 | |
|    return 0 if !$val;
 | |
|    return(make_short($val / $stats{'Uptime'}, 0, 1));
 | |
| }
 | |
| 
 | |
| sub email_report # Email given report to $op{'email'}
 | |
| {
 | |
|    print "email_report\n" if $op{debug};
 | |
| 
 | |
|    return if $WIN;
 | |
| 
 | |
|    my $report = shift;
 | |
| 
 | |
|    open SENDMAIL, "|/usr/sbin/sendmail -t";
 | |
|    print SENDMAIL "From: mariadb-report\n";
 | |
|    print SENDMAIL "To: $op{email}\n";
 | |
|    print SENDMAIL "Subject: $dbms status report on " . ($mycnf{'host'} || 'localhost') . "\n\n";
 | |
|    print SENDMAIL `cat $report`;
 | |
|    close SENDMAIL;
 | |
| }
 | |
| 
 | |
| sub cat_report # Print given report to screen
 | |
| {
 | |
|    print "cat_report\n" if $op{debug};
 | |
| 
 | |
|    my $report = shift;
 | |
|    my @report;
 | |
| 
 | |
|    open REPORT, "< $report";
 | |
|    @report = <REPORT>;
 | |
|    close REPORT;
 | |
|    print @report;
 | |
| }
 | |
| 
 | |
| sub get_Com_values
 | |
| {
 | |
|    print "get_Com_values\n" if $op{debug};
 | |
| 
 | |
|    %Com_vals = ();
 | |
| 
 | |
|    # Make copy of just the Com_ values
 | |
|    for(keys %stats)
 | |
|    {
 | |
|       if(grep /^Com_/, $_ and $stats{$_} > 0)
 | |
|       {
 | |
|          /^Com_(.*)/;
 | |
|          $Com_vals{$1} = $stats{$_};
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    # Remove DMS values
 | |
|    delete $Com_vals{'select'};
 | |
|    delete $Com_vals{'insert'};
 | |
|    delete $Com_vals{'insert_select'};
 | |
|    delete $Com_vals{'replace'};
 | |
|    delete $Com_vals{'replace_select'};
 | |
|    delete $Com_vals{'update'};
 | |
|    delete $Com_vals{'update_multi'} if exists $Com_vals{'update_multi'};
 | |
|    delete $Com_vals{'delete'};
 | |
|    delete $Com_vals{'delete_multi'} if exists $Com_vals{'delete_multi'};
 | |
| }
 | |
| 
 | |
| sub write_DTQ # Write DTQ report in descending order by values
 | |
| {
 | |
|    print "write_DTQ\n" if $op{debug};
 | |
| 
 | |
|    $~ = 'DTQ';
 | |
| 
 | |
|    my %DTQ;
 | |
|    my $first = 1;
 | |
| 
 | |
|    # Total Com values
 | |
|    $stat_val = 0;
 | |
|    for(values %Com_vals) { $stat_val += $_; }
 | |
|    $DTQ{'Com_'} = $stat_val;
 | |
| 
 | |
|    $DTQ{'DMS'}      = $dms;
 | |
|    $DTQ{'QC Hits'}  = $stats{'Qcache_hits'} if $stats{'Qcache_hits'} != 0;
 | |
|    $DTQ{'COM_QUIT'} = int (($stats{'Connections'} - 2) - ($stats{'Aborted_clients'} / 2));
 | |
| 
 | |
|    $stat_val = 0;
 | |
|    for(values %DTQ) { $stat_val += $_; }
 | |
|    if($questions != $stat_val)
 | |
|    {
 | |
|       $DTQ{($questions > $stat_val ? '+Unknown' : '-Unknown')} = abs $questions - $stat_val;
 | |
|    }
 | |
| 
 | |
|    for(sort { $DTQ{$b} <=> $DTQ{$a} } keys(%DTQ))
 | |
|    {
 | |
|       if($first) { $stat_label = '%Total:'; $first = 0; }
 | |
|       else       { $stat_label = ''; }
 | |
| 
 | |
|       $stat_name = $_;
 | |
|       $stat_val  = $DTQ{$_};
 | |
|       write;
 | |
|    }
 | |
| }
 | |
| 
 | |
| sub write_DMS # Write DMS report in descending order by values
 | |
| {
 | |
|    print "write_DMS\n" if $op{debug};
 | |
| 
 | |
|    $~ = 'DMS';
 | |
| 
 | |
|    for(sort { $DMS_vals{$b} <=> $DMS_vals{$a} } keys(%DMS_vals))
 | |
|    {
 | |
|       $stat_name = $_;
 | |
|       $stat_val  = $DMS_vals{$_};
 | |
|       write;
 | |
|    }
 | |
| }
 | |
| 
 | |
| sub write_Com # Write COM report in descending order by values
 | |
| {
 | |
|    print "write_Com\n" if $op{debug};
 | |
| 
 | |
|    my $i = $op{'com'};
 | |
| 
 | |
|    $~ = 'COM_1';
 | |
| 
 | |
|    # Total Com values and write first line of COM report
 | |
|    $stat_label = '%Total:' unless $op{'dtq'};
 | |
|    $stat_val   = 0;
 | |
|    for(values %Com_vals) { $stat_val += $_; }
 | |
|    write;
 | |
| 
 | |
|    $~ = 'COM_2';
 | |
| 
 | |
|    # Sort remaining Com values, print only the top $op{'com'} number of values
 | |
|    for(sort { $Com_vals{$b} <=> $Com_vals{$a} } keys(%Com_vals))
 | |
|    {
 | |
|       $stat_name = $_;
 | |
|       $stat_val  = $Com_vals{$_};
 | |
|       write;
 | |
| 
 | |
|       last if !(--$i);
 | |
|    }
 | |
| }
 | |
| 
 | |
| sub write_qcache
 | |
| {
 | |
|    print "write_qcache\n" if $op{debug};
 | |
| 
 | |
|    # Query cache was added in 4.0.1, but have_query_cache was added in 4.0.2,
 | |
|    # ergo this method is slightly more reliable
 | |
|    return if not exists $vars{'query_cache_size'};
 | |
|    return if $vars{'query_cache_size'} == 0;
 | |
|    return if defined($vars{'query_cache_type'}) and $vars{'query_cache_type'} eq 'OFF';
 | |
| 
 | |
|    $qc_mem_used = $vars{'query_cache_size'} - $stats{'Qcache_free_memory'};
 | |
|    $qc_hi_r = sprintf "%.2f", $stats{'Qcache_hits'} / ($stats{'Qcache_inserts'} ||= 1);
 | |
|    $qc_ip_r = sprintf "%.2f", $stats{'Qcache_inserts'} / ($stats{'Qcache_lowmem_prunes'} ||= 1);
 | |
| 
 | |
|    $~ = 'QCACHE';
 | |
|    write;
 | |
| }
 | |
| 
 | |
| sub write_Subquerycache
 | |
| {
 | |
|    print "write_Subquerycache\n" if $op{debug};
 | |
| 
 | |
|    return if not defined $stats{'Subquery_cache_hit'};
 | |
|    return if $stats{'Subquery_cache_hit'} == 0 && $stats{'Subquery_cache_miss'} == 0;
 | |
| 
 | |
|    $~ = 'SUBQUERYCACHE';
 | |
|    write;
 | |
| }
 | |
| 
 | |
| sub write_Binlog
 | |
| {
 | |
|    print "write_Binlog\n" if $op{debug};
 | |
| 
 | |
|    return if $binlog_cache_ratio == 0 && $binlog_stmt_cache_ratio == 0;
 | |
|    $~ = 'BINLOG';
 | |
|    write;
 | |
| }
 | |
| 
 | |
| sub write_InnoDB
 | |
| {
 | |
|    print "write_InnoDB\n" if $op{debug};
 | |
| 
 | |
|    return if not defined $stats{'Innodb_page_size'};
 | |
| 
 | |
|    $stats{'Innodb_buffer_pool_pages_latched'} = 0 if not defined $stats{'Innodb_buffer_pool_pages_latched'};
 | |
| 
 | |
|    $~ = 'IB';
 | |
|    write;
 | |
| 
 | |
|    # Innodb_row_lock_ values were added in MySQL 5.0.3
 | |
|    if($MySQL_version >= 50003)
 | |
|    {
 | |
|       $~ = 'IB_LOCK';
 | |
|       write;
 | |
|    }
 | |
| 
 | |
|    # Data, Pages, Rows
 | |
|    $~ = 'IB_DPR';
 | |
|    write;
 | |
| }
 | |
| 
 | |
| 
 | |
| sub write_Aria
 | |
| {
 | |
|    print "write_Aria\n" if $op{debug};
 | |
| 
 | |
|    return if not defined $stats{'Aria_pagecache_blocks_used'};
 | |
| 
 | |
|    $~ = 'PAGECACHE_BUFF_MAX';
 | |
|    write;
 | |
| 
 | |
|    if($pagecache_buffer_usage != -1) { $~ = 'PAGECACHE_BUFF_USAGE', write }
 | |
| 
 | |
|    $~ = 'PAGECACHE_RATIOS';
 | |
|    write;
 | |
| }
 | |
| 
 | |
| sub write_Rows
 | |
| {
 | |
|    print "write_Rows\n" if $op{debug};
 | |
| 
 | |
|    $rows_using_indexes = $stats{'Handler_read_first'} + $stats{'Handler_read_key'} + $stats{'Handler_read_next'} + $stats{'Handler_read_prev'};
 | |
|    $rows = $rows_using_indexes + $stats{'Handler_read_rnd'} + $stats{'Handler_read_rnd_next'} + $stats{'Sort_rows'};
 | |
| 
 | |
|    $~ = 'ROWS';
 | |
|    write;
 | |
| }
 | |
| 
 | |
| sub have_op
 | |
| {
 | |
|    my $key = shift;
 | |
|    return 1 if (exists $op{$key} && $op{$key} ne '');
 | |
|    return 0;
 | |
| }
 | |
| 
 | |
| sub sig_handler
 | |
| {
 | |
|    print "\nReceived signal at " , scalar localtime , "\n";
 | |
|    exit_tasks_and_cleanup();
 | |
|    exit;
 | |
| }
 | |
| 
 | |
| sub exit_tasks_and_cleanup
 | |
| {
 | |
|    print "exit_tasks_and_cleanup\n" if $op{debug};
 | |
| 
 | |
|    close $tmpfile_fh;
 | |
|    select STDOUT unless $op{'detach'};
 | |
| 
 | |
|    email_report($tmpfile) if $op{'email'};
 | |
| 
 | |
|    cat_report($tmpfile) unless $op{'detach'};
 | |
| 
 | |
|    if($op{'outfile'})
 | |
|    {
 | |
|       if($WIN) { `move $tmpfile $op{outfile}`; }
 | |
|       else     { `mv $tmpfile $op{outfile}`;   }
 | |
|    }
 | |
|    else
 | |
|    {
 | |
|       unlink $tmpfile;
 | |
|    }
 | |
| 
 | |
|    if(!$op{'infile'} && !$relative_infiles)
 | |
|    {
 | |
|       if($op{'flush-status'})
 | |
|       {
 | |
|          my $query = $dbh->prepare("FLUSH STATUS;");
 | |
|          $query->execute();
 | |
|          $query->finish();
 | |
|       }
 | |
|       $dbh->disconnect();
 | |
|    }
 | |
| }
 | |
| 
 | |
| #
 | |
| # Formats
 | |
| #
 | |
| 
 | |
| format MYSQL_TIME =
 | |
| @<<<<<< @<<<<<<<<<<<<<<<<<< uptime @<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<
 | |
| $dbms, $vars{'version'}, sec_to_dhms($real_uptime), (($op{infile} || $relative_infiles) ? '' : scalar localtime)
 | |
| .
 | |
| 
 | |
| format KEY_BUFF_MAX =
 | |
| 
 | |
| __ Key _________________________________________________________________
 | |
| Buffer used   @>>>>>> of  @>>>>>>   %Used: @>>>>>
 | |
| make_short($key_buffer_used, 1), make_short($vars{'key_buffer_size'}, 1), perc($key_buffer_used, $vars{'key_buffer_size'})
 | |
| .
 | |
| 
 | |
| format KEY_BUFF_USAGE =
 | |
|   Current     @>>>>>>              %Usage: @>>>>>
 | |
| make_short($key_buffer_usage, 1), perc($key_buffer_usage, $vars{'key_buffer_size'})
 | |
| .
 | |
| 
 | |
| format KEY_RATIOS =
 | |
| Write hit     @>>>>>%
 | |
| $key_write_ratio
 | |
| Read hit      @>>>>>%
 | |
| $key_read_ratio
 | |
| 
 | |
| __ Questions ___________________________________________________________
 | |
| Total       @>>>>>>>>    @>>>>>/s
 | |
| make_short($questions), t($questions)
 | |
| .
 | |
| 
 | |
| format DTQ =
 | |
|   @<<<<<<<  @>>>>>>>>    @>>>>>/s  @>>>>>> @>>>>>
 | |
| $stat_name, make_short($stat_val), t($stat_val), $stat_label, perc($stat_val, $questions)
 | |
| .
 | |
| 
 | |
| format SLOW_DMS =
 | |
| Slow @<<<<<<< @>>>>>>    @>>>>>/s          @>>>>>  %DMS: @>>>>> Log: @>>
 | |
| $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'}
 | |
| DMS         @>>>>>>>>    @>>>>>/s          @>>>>>
 | |
| make_short($dms), t($dms), perc($dms, $questions)
 | |
| .
 | |
| 
 | |
| format DMS =
 | |
|   @<<<<<<<  @>>>>>>>>    @>>>>>/s          @>>>>>        @>>>>>
 | |
| $stat_name, make_short($stat_val), t($stat_val), perc($stat_val, $questions), perc($stat_val, $dms)
 | |
| .
 | |
| 
 | |
| format COM_1 =
 | |
| Com_        @>>>>>>>>    @>>>>>/s          @>>>>>
 | |
| make_short($stat_val), t($stat_val), perc($stat_val, $questions)
 | |
| .
 | |
| 
 | |
| format COM_2 =
 | |
|   @<<<<<<<<<< @>>>>>>    @>>>>>/s          @>>>>>
 | |
| $stat_name, make_short($stat_val), t($stat_val), perc($stat_val, $questions)
 | |
| .
 | |
| 
 | |
| format SAS =
 | |
| 
 | |
| __ SELECT and Sort _____________________________________________________
 | |
| Scan          @>>>>>>    @>>>>>/s %SELECT: @>>>>>
 | |
| make_short($stats{'Select_scan'}), t($stats{'Select_scan'}), perc($stats{'Select_scan'}, $stats{'Com_select'})
 | |
| Range         @>>>>>>    @>>>>>/s          @>>>>>
 | |
| make_short($stats{'Select_range'}), t($stats{'Select_range'}), perc($stats{'Select_range'}, $stats{'Com_select'})
 | |
| Full join     @>>>>>>    @>>>>>/s          @>>>>>
 | |
| make_short($stats{'Select_full_join'}), t($stats{'Select_full_join'}), perc($stats{'Select_full_join'}, $stats{'Com_select'})
 | |
| Range check   @>>>>>>    @>>>>>/s          @>>>>>
 | |
| make_short($stats{'Select_range_check'}), t($stats{'Select_range_check'}), perc($stats{'Select_range_check'}, $stats{'Com_select'})
 | |
| Full rng join @>>>>>>    @>>>>>/s          @>>>>>
 | |
| make_short($stats{'Select_full_range_join'}), t($stats{'Select_full_range_join'}), perc($stats{'Select_full_range_join'}, $stats{'Com_select'})
 | |
| Sort scan     @>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Sort_scan'}), t($stats{'Sort_scan'})
 | |
| Sort range    @>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Sort_range'}), t($stats{'Sort_range'})
 | |
| Sort mrg pass @>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Sort_merge_passes'}), t($stats{'Sort_merge_passes'})
 | |
| .
 | |
| 
 | |
| format QCACHE =
 | |
| 
 | |
| __ Query Cache _________________________________________________________
 | |
| Memory usage  @>>>>>> of  @>>>>>>  %Usage: @>>>>>
 | |
| make_short($qc_mem_used, 1), make_short($vars{'query_cache_size'}, 1), perc($qc_mem_used, $vars{'query_cache_size'})
 | |
| Block Fragment @>>>>>%
 | |
| perc($stats{'Qcache_free_blocks'}, $stats{'Qcache_total_blocks'})
 | |
| Hits          @>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Qcache_hits'}), t($stats{'Qcache_hits'})
 | |
| Inserts       @>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Qcache_inserts'}), t($stats{'Qcache_inserts'})
 | |
| Insrt:Prune @>>>>>>:1    @>>>>>/s
 | |
| make_short($qc_ip_r), t($stats{'Qcache_inserts'} - $stats{'Qcache_lowmem_prunes'})
 | |
| Hit:Insert  @>>>>>>:1
 | |
| $qc_hi_r, t($qc_hi_r)
 | |
| .
 | |
| 
 | |
| format SUBQUERYCACHE =
 | |
| 
 | |
| __ Subquery Cache ______________________________________________________
 | |
| Hit ratio     @>>>>>%
 | |
| perc($stats{'Subquery_cache_hit'} / ($stats{'Subquery_cache_hit'} + $stats{'Subquery_cache_miss'}))
 | |
| Hits          @>>>>>>   @>>>>>/s
 | |
| make_short($stats{'Subquery_cache_hit'}), t($stats{'Subquery_cache_hit'})
 | |
| Miss          @>>>>>>   @>>>>>/s
 | |
| make_short($stats{'Subquery_cache_miss'}), t($stats{'Subquery_cache_miss'})
 | |
| .
 | |
| 
 | |
| # Not really the end...
 | |
| format REPORT_END =
 | |
| 
 | |
| __ Table Locks _________________________________________________________
 | |
| Waited      @>>>>>>>>    @>>>>>/s  %Total: @>>>>>
 | |
| make_short($stats{'Table_locks_waited'}), t($stats{'Table_locks_waited'}), perc($stats{'Table_locks_waited'}, $stats{'Table_locks_waited'} + $stats{'Table_locks_immediate'});
 | |
| Immediate   @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Table_locks_immediate'}), t($stats{'Table_locks_immediate'})
 | |
| 
 | |
| __ Tables ______________________________________________________________
 | |
| Open        @>>>>>>>> of @>>>>>    %Cache: @>>>>>
 | |
| $stats{'Open_tables'}, $vars{'table_cache'}, perc($stats{'Open_tables'}, $vars{'table_cache'})
 | |
| Opened      @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Opened_tables'}), t($stats{'Opened_tables'})
 | |
| 
 | |
| __ Connections _________________________________________________________
 | |
| Max used    @>>>>>>>> of @>>>>>      %Max: @>>>>>
 | |
| $stats{'Max_used_connections'}, $vars{'max_connections'}, perc($stats{'Max_used_connections'}, $vars{'max_connections'})
 | |
| Total       @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Connections'}), t($stats{'Connections'})
 | |
| 
 | |
| __ Created Temp ________________________________________________________
 | |
| Disk table  @>>>>>>>>    @>>>>>/s   %Disk: @>>>>>
 | |
| make_short($stats{'Created_tmp_disk_tables'}), t($stats{'Created_tmp_disk_tables'}), perc($stats{'Created_tmp_disk_tables'}, $stats{'Created_tmp_tables'})
 | |
| Table       @>>>>>>>>    @>>>>>/s    Size: @>>>>>
 | |
| make_short($stats{'Created_tmp_tables'}), t($stats{'Created_tmp_tables'}), make_short($vars{'tmp_table_size'}, 1, 1)
 | |
| File        @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Created_tmp_files'}), t($stats{'Created_tmp_files'})
 | |
| .
 | |
| 
 | |
| format THREADS =
 | |
| 
 | |
| __ Threads _____________________________________________________________
 | |
| Running     @>>>>>>>> of @>>>>>
 | |
| $stats{'Threads_running'}, $stats{'Threads_connected'}
 | |
| Created     @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Threads_created'}), t($stats{'Threads_created'})
 | |
| Slow        @>>>>>>>>    @>>>>>/s
 | |
| $stats{'Slow_launch_threads'}, t($stats{'Slow_launch_threads'})
 | |
| .
 | |
| 
 | |
| format THREADPERCONNECTION =
 | |
| Cached      @>>>>>>>> of @>>>>>      %Hit: @>>>>>
 | |
| $stats{'Threads_cached'}, $vars{'thread_cache_size'}, make_short(100 - perc($stats{'Threads_created'}, $stats{'Connections'}))
 | |
| .
 | |
| 
 | |
| format THREADPOOL =
 | |
| Threadpool  @>>>>>>>> of @>>>>>     %Used: @>>>>>
 | |
| $stats{'Threadpool_threads'} + $stats{'Threadpool_idle_threads'}, $vars{'thread_pool_max_threads'}, make_short(perc($stats{'Threadpool_threads'} + $stats{'Threadpool_idle_threads'}, $vars{'thread_pool_max_threads'}))
 | |
|   Running   @>>>>>>>> of @>>>>>  %Running: @>>>>>
 | |
| $stats{'Threadpool_threads'}, $vars{'thread_pool_max_threads'}, make_short(perc($stats{'Threadpool_threads'}, $vars{'thread_pool_max_threads'}))
 | |
|   Idle      @>>>>>>>> of @>>>>>     %Idle: @>>>>>
 | |
| $stats{'Threadpool_idle_threads'}, $vars{'thread_pool_max_threads'}, make_short(perc($stats{'Threadpool_idle_threads'}, $vars{'thread_pool_max_threads'}))
 | |
| .
 | |
| 
 | |
| format TAB =
 | |
| 
 | |
| __ Aborted _____________________________________________________________
 | |
| Clients     @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Aborted_clients'}), t($stats{'Aborted_clients'})
 | |
| Connects    @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Aborted_connects'}), t($stats{'Aborted_connects'})
 | |
| 
 | |
| __ Bytes _______________________________________________________________
 | |
| Sent        @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Bytes_sent'}), t($stats{'Bytes_sent'})
 | |
| Received    @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Bytes_received'}), t($stats{'Bytes_received'})
 | |
| .
 | |
| 
 | |
| format IB =
 | |
| 
 | |
| __ InnoDB Buffer Pool __________________________________________________
 | |
| Usage         @>>>>>> of  @>>>>>>  %Usage: @>>>>>
 | |
| make_short($ib_bp_used, 1), make_short($ib_bp_total, 1), perc($ib_bp_used, $ib_bp_total)
 | |
| Read hit      @>>>>>%
 | |
| $ib_bp_read_ratio;
 | |
| Pages
 | |
|   Free      @>>>>>>>>              %Total: @>>>>>
 | |
| make_short($stats{'Innodb_buffer_pool_pages_free'}), perc($stats{'Innodb_buffer_pool_pages_free'}, $stats{'Innodb_buffer_pool_pages_total'})
 | |
|   Data      @>>>>>>>>                      @>>>>>  %Drty: @>>>>>
 | |
| make_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'})
 | |
|   Misc      @>>>>>>>>                      @>>>>>
 | |
|   $stats{'Innodb_buffer_pool_pages_misc'}, perc($stats{'Innodb_buffer_pool_pages_misc'}, $stats{'Innodb_buffer_pool_pages_total'})
 | |
|   Latched   @>>>>>>>>                      @>>>>>
 | |
| $stats{'Innodb_buffer_pool_pages_latched'}, perc($stats{'Innodb_buffer_pool_pages_latched'}, $stats{'Innodb_buffer_pool_pages_total'})
 | |
| Reads       @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_buffer_pool_read_requests'}), t($stats{'Innodb_buffer_pool_read_requests'})
 | |
|   From disk @>>>>>>>>    @>>>>>/s   %Disk: @>>>>>
 | |
| make_short($stats{'Innodb_buffer_pool_reads'}), t($stats{'Innodb_buffer_pool_reads'}), perc($stats{'Innodb_buffer_pool_reads'}, $stats{'Innodb_buffer_pool_read_requests'})
 | |
|   Ahead Rnd @>>>>>>>>    @>>>>>/s
 | |
| $stats{'Innodb_buffer_pool_read_ahead_rnd'}, t($stats{'Innodb_buffer_pool_read_ahead_rnd'})
 | |
| #  Ahead Sql @>>>>>>>>    @>>>>>/s
 | |
| #$stats{'Innodb_buffer_pool_read_ahead_seq'}, t($stats{'Innodb_buffer_pool_read_ahead_seq'})
 | |
| Writes      @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_buffer_pool_write_requests'}), t($stats{'Innodb_buffer_pool_write_requests'})
 | |
| Wait Free   @>>>>>>>>    @>>>>>/s   %Wait: @>>>>>
 | |
| $stats{'Innodb_buffer_pool_wait_free'}, t($stats{'Innodb_buffer_pool_wait_free'}), perc($stats{'Innodb_buffer_pool_wait_free'}, $stats{'Innodb_buffer_pool_write_requests'})
 | |
| Flushes     @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_buffer_pool_pages_flushed'}), t($stats{'Innodb_buffer_pool_pages_flushed'})
 | |
| .
 | |
| 
 | |
| format IB_LOCK =
 | |
| 
 | |
| __ InnoDB Lock _________________________________________________________
 | |
| Waits       @>>>>>>>>    @>>>>>/s
 | |
| $stats{'Innodb_row_lock_waits'}, t($stats{'Innodb_row_lock_waits'})
 | |
| Current     @>>>>>>>>
 | |
| $stats{'Innodb_row_lock_current_waits'}
 | |
| Time acquiring
 | |
|   Total     @>>>>>>>> ms
 | |
| $stats{'Innodb_row_lock_time'}
 | |
|   Average   @>>>>>>>> ms
 | |
| $stats{'Innodb_row_lock_time_avg'}
 | |
|   Max       @>>>>>>>> ms
 | |
| $stats{'Innodb_row_lock_time_max'}
 | |
| .
 | |
| 
 | |
| format IB_DPR =
 | |
| 
 | |
| __ InnoDB Data, Pages, Rows ____________________________________________
 | |
| Data
 | |
|   Reads     @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_data_reads'}), t($stats{'Innodb_data_reads'})
 | |
|   Writes    @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_data_writes'}), t($stats{'Innodb_data_writes'})
 | |
|   fsync     @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_data_fsyncs'}), t($stats{'Innodb_data_fsyncs'})
 | |
|   Pending
 | |
|     Reads   @>>>>>>>>
 | |
| $stats{'Innodb_data_pending_reads'}, t($stats{'Innodb_data_pending_reads'})
 | |
|     Writes  @>>>>>>>>
 | |
| $stats{'Innodb_data_pending_writes'}, t($stats{'Innodb_data_pending_writes'})
 | |
|     fsync   @>>>>>>>>
 | |
| $stats{'Innodb_data_pending_fsyncs'}, t($stats{'Innodb_data_pending_fsyncs'})
 | |
| 
 | |
| Pages
 | |
|   Created   @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_pages_created'}), t($stats{'Innodb_pages_created'})
 | |
|   Read      @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_pages_read'}), t($stats{'Innodb_pages_read'})
 | |
|   Written   @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_pages_written'}), t($stats{'Innodb_pages_written'})
 | |
| 
 | |
| Rows
 | |
|   Deleted   @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_rows_deleted'}), t($stats{'Innodb_rows_deleted'})
 | |
|   Inserted  @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_rows_inserted'}), t($stats{'Innodb_rows_inserted'})
 | |
|   Read      @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_rows_read'}), t($stats{'Innodb_rows_read'})
 | |
|   Updated   @>>>>>>>>    @>>>>>/s
 | |
| make_short($stats{'Innodb_rows_updated'}), t($stats{'Innodb_rows_updated'})
 | |
| .
 | |
| 
 | |
| format PAGECACHE_BUFF_MAX =
 | |
| 
 | |
| __ Aria Pagecache ______________________________________________________
 | |
| Buffer used   @>>>>>> of  @>>>>>>   %Used: @>>>>>
 | |
| make_short($pagecache_buffer_used, 1), make_short($vars{'aria_pagecache_buffer_size'}, 1), perc($pagecache_buffer_used, $vars{'aria_pagecache_buffer_size'})
 | |
| .
 | |
| 
 | |
| format PAGECACHE_BUFF_USAGE =
 | |
|   Current     @>>>>>>              %Usage: @>>>>>
 | |
| make_short($pagecache_buffer_usage, 1), perc($pagecache_buffer_usage, $vars{'aria_pagecache_buffer_size'})
 | |
| .
 | |
| 
 | |
| format PAGECACHE_RATIOS =
 | |
| Write hit     @>>>>>%
 | |
| $pagecache_write_ratio
 | |
| Read hit      @>>>>>%
 | |
| $pagecache_read_ratio
 | |
| .
 | |
| 
 | |
| format BINLOG =
 | |
| 
 | |
| __ Binary Log Cache _____________________________________________________
 | |
| Disk use
 | |
|   Transactional		@>>>>>%
 | |
| perc($binlog_cache_ratio)
 | |
|   Non transactional	@>>>>>%
 | |
| perc($binlog_stmt_cache_ratio)
 | |
| .
 | |
| 
 | |
| format ROWS =
 | |
| 
 | |
| __ Rows ________________________________________________________________
 | |
| Rows        @>>>>>>>>    @>>>>>/s
 | |
| make_short($rows), t($rows)
 | |
|   Using idx @>>>>>>>>    @>>>>>/s  %Index: @>>>>>
 | |
| make_short($rows_using_indexes), t($rows_using_indexes), perc($rows_using_indexes,$rows)
 | |
| Rows/question @>>>>>>
 | |
| make_short($rows/$questions)
 | |
| .
 | 
