(#12412) mysqltuner.pl update
This was an update from the upstream source: https://github.com/rackerhacker/MySQLTuner-perl/blob/master/mysqltuner.pl
This commit is contained in:
parent
2f5615688f
commit
b809e6fd75
1 changed files with 181 additions and 98 deletions
|
@ -1,10 +1,10 @@
|
|||
#!/usr/bin/perl -w
|
||||
# mysqltuner.pl - Version 1.0.0
|
||||
# mysqltuner.pl - Version 1.2.0
|
||||
# High Performance MySQL Tuning Script
|
||||
# Copyright (C) 2006-2008 Major Hayden - major@mhtx.net
|
||||
# Copyright (C) 2006-2011 Major Hayden - major@mhtx.net
|
||||
#
|
||||
# For the latest updates, please visit http://mysqltuner.com/
|
||||
# Subversion repository available at http://tools.assembla.com/svn/mysqltuner/
|
||||
# Git repository available at http://github.com/rackerhacker/MySQLTuner-perl
|
||||
#
|
||||
# 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
|
||||
|
@ -20,17 +20,16 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# This project would not be possible without help from:
|
||||
# Matthew Montgomery Paul Kehrer
|
||||
# Dave Burgess Jonathan Hinds
|
||||
# Mike Jackson Nils Breunese
|
||||
# Shawn Ashlee Luuk Vosslamber
|
||||
# Ville Skytta Trent Hornibrook
|
||||
# Jason Gill Mark Imbriaco
|
||||
# Greg Eden Aubin Galinotti
|
||||
# Giovanni Bechis Bill Bradford
|
||||
# Ryan Novosielski Michael Scheidell
|
||||
# Blair Christensen Hans du Plooy
|
||||
# Victor Trac Everett Barnes
|
||||
# Matthew Montgomery Paul Kehrer Dave Burgess
|
||||
# Jonathan Hinds Mike Jackson Nils Breunese
|
||||
# Shawn Ashlee Luuk Vosslamber Ville Skytta
|
||||
# Trent Hornibrook Jason Gill Mark Imbriaco
|
||||
# Greg Eden Aubin Galinotti Giovanni Bechis
|
||||
# Bill Bradford Ryan Novosielski Michael Scheidell
|
||||
# Blair Christensen Hans du Plooy Victor Trac
|
||||
# Everett Barnes Tom Krouper Gary Barrueto
|
||||
# Simon Greenaway Adam Stein Isart Montane
|
||||
# Baptiste M.
|
||||
#
|
||||
# Inspired by Matthew Montgomery's tuning-primer.sh script:
|
||||
# http://forge.mysql.com/projects/view.php?id=44
|
||||
|
@ -38,29 +37,30 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use diagnostics;
|
||||
use File::Spec;
|
||||
use Getopt::Long;
|
||||
|
||||
# Set up a few variables for use in the script
|
||||
my $tunerversion = "1.0.0";
|
||||
my $tunerversion = "1.2.0";
|
||||
my (@adjvars, @generalrec);
|
||||
|
||||
# Set defaults
|
||||
my %opt = (
|
||||
"nobad" => 0,
|
||||
"nogood" => 0,
|
||||
"noinfo" => 0,
|
||||
"nocolor" => 0,
|
||||
"forcemem" => 0,
|
||||
"forceswap" => 0,
|
||||
"host" => 0,
|
||||
"socket" => 0,
|
||||
"port" => 0,
|
||||
"user" => 0,
|
||||
"pass" => 0,
|
||||
"skipsize" => 0,
|
||||
"checkversion" => 0,
|
||||
"nobad" => 0,
|
||||
"nogood" => 0,
|
||||
"noinfo" => 0,
|
||||
"nocolor" => 0,
|
||||
"forcemem" => 0,
|
||||
"forceswap" => 0,
|
||||
"host" => 0,
|
||||
"socket" => 0,
|
||||
"port" => 0,
|
||||
"user" => 0,
|
||||
"pass" => 0,
|
||||
"skipsize" => 0,
|
||||
"checkversion" => 0,
|
||||
);
|
||||
|
||||
|
||||
# Gather the options from the command line
|
||||
GetOptions(\%opt,
|
||||
'nobad',
|
||||
|
@ -117,17 +117,19 @@ sub usage {
|
|||
exit;
|
||||
}
|
||||
|
||||
my $devnull = File::Spec->devnull();
|
||||
|
||||
# Setting up the colors for the print styles
|
||||
my $good = ($opt{nocolor} == 0)? "[\e[00;32mOK\e[00m]" : "[OK]" ;
|
||||
my $bad = ($opt{nocolor} == 0)? "[\e[00;31m!!\e[00m]" : "[!!]" ;
|
||||
my $info = ($opt{nocolor} == 0)? "[\e[00;34m--\e[00m]" : "[--]" ;
|
||||
my $good = ($opt{nocolor} == 0)? "[\e[0;32mOK\e[0m]" : "[OK]" ;
|
||||
my $bad = ($opt{nocolor} == 0)? "[\e[0;31m!!\e[0m]" : "[!!]" ;
|
||||
my $info = ($opt{nocolor} == 0)? "[\e[0;34m--\e[0m]" : "[--]" ;
|
||||
|
||||
# Functions that handle the print styles
|
||||
sub goodprint { print $good." ".$_[0] unless ($opt{nogood} == 1); }
|
||||
sub infoprint { print $info." ".$_[0] unless ($opt{noinfo} == 1); }
|
||||
sub badprint { print $bad." ".$_[0] unless ($opt{nobad} == 1); }
|
||||
sub redwrap { return ($opt{nocolor} == 0)? "\e[00;31m".$_[0]."\e[00m" : $_[0] ; }
|
||||
sub greenwrap { return ($opt{nocolor} == 0)? "\e[00;32m".$_[0]."\e[00m" : $_[0] ; }
|
||||
sub redwrap { return ($opt{nocolor} == 0)? "\e[0;31m".$_[0]."\e[0m" : $_[0] ; }
|
||||
sub greenwrap { return ($opt{nocolor} == 0)? "\e[0;32m".$_[0]."\e[0m" : $_[0] ; }
|
||||
|
||||
# Calculates the parameter passed in bytes, and then rounds it to one decimal place
|
||||
sub hr_bytes {
|
||||
|
@ -227,9 +229,16 @@ sub os_setup {
|
|||
$physical_memory = `sysctl -n hw.realmem`;
|
||||
$swap_memory = `swapinfo | grep '^/' | awk '{ s+= \$2 } END { print s }'`;
|
||||
} elsif ($os =~ /SunOS/) {
|
||||
$physical_memory = `/usr/sbin/prtconf | grep Memory | awk '{print \$3}'` or memerror;
|
||||
$physical_memory = `/usr/sbin/prtconf | grep Memory | cut -f 3 -d ' '` or memerror;
|
||||
chomp($physical_memory);
|
||||
$physical_memory = $physical_memory*1024*1024;
|
||||
} elsif ($os =~ /AIX/) {
|
||||
$physical_memory = `lsattr -El sys0 | grep realmem | awk '{print \$2}'` or memerror;
|
||||
chomp($physical_memory);
|
||||
$physical_memory = $physical_memory*1024;
|
||||
$swap_memory = `lsps -as | awk -F"(MB| +)" '/MB /{print \$2}'` or memerror;
|
||||
chomp($swap_memory);
|
||||
$swap_memory = $swap_memory*1024*1024;
|
||||
}
|
||||
}
|
||||
chomp($physical_memory);
|
||||
|
@ -283,14 +292,25 @@ sub mysql_setup {
|
|||
badprint "Attempted to use login credentials from Plesk, but they failed.\n";
|
||||
exit 0;
|
||||
}
|
||||
} elsif ( -r "/etc/mysql/debian.cnf" and $doremote == 0 ){
|
||||
# We have a debian maintenance account, use it
|
||||
$mysqllogin = "--defaults-file=/etc/mysql/debian.cnf";
|
||||
my $loginstatus = `mysqladmin $mysqllogin ping 2>&1`;
|
||||
if ($loginstatus =~ /mysqld is alive/) {
|
||||
goodprint "Logged in using credentials from debian maintenance account.\n";
|
||||
return 1;
|
||||
} else {
|
||||
badprint "Attempted to use login credentials from debian maintenance account, but they failed.\n";
|
||||
exit 0;
|
||||
}
|
||||
} else {
|
||||
# It's not Plesk, we should try a login
|
||||
# It's not Plesk or debian, we should try a login
|
||||
my $loginstatus = `mysqladmin $remotestring ping 2>&1`;
|
||||
if ($loginstatus =~ /mysqld is alive/) {
|
||||
# Login went just fine
|
||||
$mysqllogin = " $remotestring ";
|
||||
# Did this go well because of a .my.cnf file or is there no password set?
|
||||
my $userpath = `ls -d ~ 2>/dev/null`;
|
||||
my $userpath = `printenv HOME`;
|
||||
if (length($userpath) > 0) {
|
||||
chomp($userpath);
|
||||
}
|
||||
|
@ -302,9 +322,9 @@ sub mysql_setup {
|
|||
print STDERR "Please enter your MySQL administrative login: ";
|
||||
my $name = <>;
|
||||
print STDERR "Please enter your MySQL administrative password: ";
|
||||
system("stty -echo");
|
||||
system("stty -echo >$devnull 2>&1");
|
||||
my $password = <>;
|
||||
system("stty echo");
|
||||
system("stty echo >$devnull 2>&1");
|
||||
chomp($password);
|
||||
chomp($name);
|
||||
$mysqllogin = "-u $name";
|
||||
|
@ -348,6 +368,52 @@ sub get_all_vars {
|
|||
$line =~ /([a-zA-Z_]*)\s*(.*)/;
|
||||
$mystat{$1} = $2;
|
||||
}
|
||||
# Workaround for MySQL bug #59393 wrt. ignore-builtin-innodb
|
||||
if (($myvar{'ignore_builtin_innodb'} || "") eq "ON") {
|
||||
$myvar{'have_innodb'} = "NO";
|
||||
}
|
||||
# have_* for engines is deprecated and will be removed in MySQL 5.6;
|
||||
# check SHOW ENGINES and set corresponding old style variables.
|
||||
# Also works around MySQL bug #59393 wrt. skip-innodb
|
||||
my @mysqlenginelist = `mysql $mysqllogin -Bse "SHOW ENGINES;" 2>$devnull`;
|
||||
foreach my $line (@mysqlenginelist) {
|
||||
if ($line =~ /^([a-zA-Z_]+)\s+(\S+)/) {
|
||||
my $engine = lc($1);
|
||||
if ($engine eq "federated" || $engine eq "blackhole") {
|
||||
$engine .= "_engine";
|
||||
} elsif ($engine eq "berkeleydb") {
|
||||
$engine = "bdb";
|
||||
}
|
||||
my $val = ($2 eq "DEFAULT") ? "YES" : $2;
|
||||
$myvar{"have_$engine"} = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub security_recommendations {
|
||||
print "\n-------- Security Recommendations -------------------------------------------\n";
|
||||
my @mysqlstatlist = `mysql $mysqllogin -Bse "SELECT CONCAT(user, '\@', host) FROM mysql.user WHERE password = '' OR password IS NULL;"`;
|
||||
if (@mysqlstatlist) {
|
||||
foreach my $line (sort @mysqlstatlist) {
|
||||
chomp($line);
|
||||
badprint "User '".$line."' has no password set.\n";
|
||||
}
|
||||
} else {
|
||||
goodprint "All database users have passwords assigned\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub get_replication_status {
|
||||
my $slave_status = `mysql $mysqllogin -Bse "show slave status\\G"`;
|
||||
my ($io_running) = ($slave_status =~ /slave_io_running\S*\s+(\S+)/i);
|
||||
my ($sql_running) = ($slave_status =~ /slave_sql_running\S*\s+(\S+)/i);
|
||||
if ($io_running eq 'Yes' && $sql_running eq 'Yes') {
|
||||
if ($myvar{'read_only'} eq 'OFF') {
|
||||
badprint "This replication slave is running with the read_only option disabled.";
|
||||
} else {
|
||||
goodprint "This replication slave is running with the read_only option enabled.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Checks for updates to MySQLTuner
|
||||
|
@ -360,10 +426,10 @@ sub validate_tuner_version {
|
|||
my $update;
|
||||
my $url = "http://mysqltuner.com/versioncheck.php?v=$tunerversion";
|
||||
if (-e "/usr/bin/curl") {
|
||||
$update = `/usr/bin/curl --connect-timeout 5 '$url' 2>/dev/null`;
|
||||
$update = `/usr/bin/curl --connect-timeout 5 '$url' 2>$devnull`;
|
||||
chomp($update);
|
||||
} elsif (-e "/usr/bin/wget") {
|
||||
$update = `/usr/bin/wget -e timestamping=off -T 5 -O - '$url' 2>/dev/null`;
|
||||
$update = `/usr/bin/wget -e timestamping=off -T 5 -O - '$url' 2>$devnull`;
|
||||
chomp($update);
|
||||
}
|
||||
if ($update eq 1) {
|
||||
|
@ -379,15 +445,21 @@ sub validate_tuner_version {
|
|||
my ($mysqlvermajor,$mysqlverminor);
|
||||
sub validate_mysql_version {
|
||||
($mysqlvermajor,$mysqlverminor) = $myvar{'version'} =~ /(\d)\.(\d)/;
|
||||
if ($mysqlvermajor < 5) {
|
||||
if (!mysql_version_ge(5)) {
|
||||
badprint "Your MySQL version ".$myvar{'version'}." is EOL software! Upgrade soon!\n";
|
||||
} elsif ($mysqlvermajor == 5) {
|
||||
goodprint "Currently running supported MySQL version ".$myvar{'version'}."\n";
|
||||
} else {
|
||||
} elsif (mysql_version_ge(6)) {
|
||||
badprint "Currently running unsupported MySQL version ".$myvar{'version'}."\n";
|
||||
} else {
|
||||
goodprint "Currently running supported MySQL version ".$myvar{'version'}."\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Checks if MySQL version is greater than equal to (major, minor)
|
||||
sub mysql_version_ge {
|
||||
my ($maj, $min) = @_;
|
||||
return $mysqlvermajor > $maj || ($mysqlvermajor == $maj && $mysqlverminor >= ($min || 0));
|
||||
}
|
||||
|
||||
# Checks for 32-bit boxes with more than 2GB of RAM
|
||||
my ($arch);
|
||||
sub check_architecture {
|
||||
|
@ -398,6 +470,9 @@ sub check_architecture {
|
|||
} elsif (`uname` !~ /SunOS/ && `uname -m` =~ /64/) {
|
||||
$arch = 64;
|
||||
goodprint "Operating on 64-bit architecture\n";
|
||||
} elsif (`uname` =~ /AIX/ && `bootinfo -K` =~ /64/) {
|
||||
$arch = 64;
|
||||
goodprint "Operating on 64-bit architecture\n";
|
||||
} else {
|
||||
$arch = 32;
|
||||
if ($physical_memory > 2147483648) {
|
||||
|
@ -421,14 +496,14 @@ sub check_storage_engines {
|
|||
my $engines;
|
||||
$engines .= (defined $myvar{'have_archive'} && $myvar{'have_archive'} eq "YES")? greenwrap "+Archive " : redwrap "-Archive " ;
|
||||
$engines .= (defined $myvar{'have_bdb'} && $myvar{'have_bdb'} eq "YES")? greenwrap "+BDB " : redwrap "-BDB " ;
|
||||
$engines .= (defined $myvar{'have_federated'} && $myvar{'have_federated'} eq "YES")? greenwrap "+Federated " : redwrap "-Federated " ;
|
||||
$engines .= (defined $myvar{'have_federated_engine'} && $myvar{'have_federated_engine'} eq "YES")? greenwrap "+Federated " : redwrap "-Federated " ;
|
||||
$engines .= (defined $myvar{'have_innodb'} && $myvar{'have_innodb'} eq "YES")? greenwrap "+InnoDB " : redwrap "-InnoDB " ;
|
||||
$engines .= (defined $myvar{'have_isam'} && $myvar{'have_isam'} eq "YES")? greenwrap "+ISAM " : redwrap "-ISAM " ;
|
||||
$engines .= (defined $myvar{'have_ndbcluster'} && $myvar{'have_ndbcluster'} eq "YES")? greenwrap "+NDBCluster " : redwrap "-NDBCluster " ;
|
||||
$engines .= (defined $myvar{'have_ndbcluster'} && $myvar{'have_ndbcluster'} eq "YES")? greenwrap "+NDBCluster " : redwrap "-NDBCluster " ;
|
||||
print "$engines\n";
|
||||
if ($mysqlvermajor >= 5) {
|
||||
if (mysql_version_ge(5)) {
|
||||
# MySQL 5 servers can have table sizes calculated quickly from information schema
|
||||
my @templist = `mysql $mysqllogin -Bse "SELECT ENGINE,SUM(DATA_LENGTH),COUNT(ENGINE) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','mysql') GROUP BY ENGINE ORDER BY ENGINE ASC;"`;
|
||||
my @templist = `mysql $mysqllogin -Bse "SELECT ENGINE,SUM(DATA_LENGTH),COUNT(ENGINE) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','mysql') AND ENGINE IS NOT NULL GROUP BY ENGINE ORDER BY ENGINE ASC;"`;
|
||||
foreach my $line (@templist) {
|
||||
my ($engine,$size,$count);
|
||||
($engine,$size,$count) = $line =~ /([a-zA-Z_]*)\s+(\d+)\s+(\d+)/;
|
||||
|
@ -436,7 +511,7 @@ sub check_storage_engines {
|
|||
$enginestats{$engine} = $size;
|
||||
$enginecount{$engine} = $count;
|
||||
}
|
||||
$fragtables = `mysql $mysqllogin -Bse "SELECT COUNT(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','mysql') AND Data_free > 0"`;
|
||||
$fragtables = `mysql $mysqllogin -Bse "SELECT COUNT(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','mysql') AND Data_free > 0 AND NOT ENGINE='MEMORY';"`;
|
||||
chomp($fragtables);
|
||||
} else {
|
||||
# MySQL < 5 servers take a lot of work to get table sizes
|
||||
|
@ -446,23 +521,17 @@ sub check_storage_engines {
|
|||
foreach my $db (@dblist) {
|
||||
chomp($db);
|
||||
if ($db eq "information_schema") { next; }
|
||||
if ($mysqlvermajor == 3 || ($mysqlvermajor == 4 && $mysqlverminor == 0)) {
|
||||
# MySQL 3.23/4.0 keeps Data_Length in the 6th column
|
||||
push (@tblist,`mysql $mysqllogin -Bse "SHOW TABLE STATUS FROM \\\`$db\\\`" | awk '{print \$2,\$6,\$9}'`);
|
||||
} else {
|
||||
# MySQL 4.1+ keeps Data_Length in the 7th column
|
||||
push (@tblist,`mysql $mysqllogin -Bse "SHOW TABLE STATUS FROM \\\`$db\\\`" | awk '{print \$2,\$7,\$10}'`);
|
||||
my @ixs = (1, 6, 9);
|
||||
if (!mysql_version_ge(4, 1)) {
|
||||
# MySQL 3.23/4.0 keeps Data_Length in the 5th (0-based) column
|
||||
@ixs = (1, 5, 8);
|
||||
}
|
||||
push(@tblist, map { [ (split)[@ixs] ] } `mysql $mysqllogin -Bse "SHOW TABLE STATUS FROM \\\`$db\\\`"`);
|
||||
}
|
||||
# Parse through the table list to generate storage engine counts/statistics
|
||||
$fragtables = 0;
|
||||
foreach my $line (@tblist) {
|
||||
chomp($line);
|
||||
$line =~ /([a-zA-Z_]*)\s+(\d+)\s+(\d+)/;
|
||||
my $engine = $1;
|
||||
my $size = $2;
|
||||
my $datafree = $3;
|
||||
if ($size !~ /^\d+$/) { $size = 0; }
|
||||
foreach my $tbl (@tblist) {
|
||||
my ($engine, $size, $datafree) = @$tbl;
|
||||
if (defined $enginestats{$engine}) {
|
||||
$enginestats{$engine} += $size;
|
||||
$enginecount{$engine} += 1;
|
||||
|
@ -507,7 +576,7 @@ sub calculations {
|
|||
exit 0;
|
||||
}
|
||||
# Per-thread memory
|
||||
if ($mysqlvermajor > 3) {
|
||||
if (mysql_version_ge(4)) {
|
||||
$mycalc{'per_thread_buffers'} = $myvar{'read_buffer_size'} + $myvar{'read_rnd_buffer_size'} + $myvar{'sort_buffer_size'} + $myvar{'thread_stack'} + $myvar{'join_buffer_size'};
|
||||
} else {
|
||||
$mycalc{'per_thread_buffers'} = $myvar{'record_buffer'} + $myvar{'record_rnd_buffer'} + $myvar{'sort_buffer'} + $myvar{'thread_stack'} + $myvar{'join_buffer_size'};
|
||||
|
@ -530,31 +599,35 @@ sub calculations {
|
|||
|
||||
# Slow queries
|
||||
$mycalc{'pct_slow_queries'} = int(($mystat{'Slow_queries'}/$mystat{'Questions'}) * 100);
|
||||
|
||||
|
||||
# Connections
|
||||
$mycalc{'pct_connections_used'} = int(($mystat{'Max_used_connections'}/$myvar{'max_connections'}) * 100);
|
||||
$mycalc{'pct_connections_used'} = ($mycalc{'pct_connections_used'} > 100) ? 100 : $mycalc{'pct_connections_used'} ;
|
||||
|
||||
|
||||
# Key buffers
|
||||
if ($mysqlvermajor > 3 && !($mysqlvermajor == 4 && $mysqlverminor == 0)) {
|
||||
if (mysql_version_ge(4, 1)) {
|
||||
$mycalc{'pct_key_buffer_used'} = sprintf("%.1f",(1 - (($mystat{'Key_blocks_unused'} * $myvar{'key_cache_block_size'}) / $myvar{'key_buffer_size'})) * 100);
|
||||
}
|
||||
if ($mystat{'Key_read_requests'} > 0) {
|
||||
$mycalc{'pct_keys_from_mem'} = sprintf("%.1f",(100 - (($mystat{'Key_reads'} / $mystat{'Key_read_requests'}) * 100)));
|
||||
} else {
|
||||
$mycalc{'pct_keys_from_mem'} = 0;
|
||||
}
|
||||
if ($doremote eq 0 and $mysqlvermajor < 5) {
|
||||
$mycalc{'total_myisam_indexes'} = `find $myvar{'datadir'} -name '*.MYI' 2>&1 | xargs du -L $duflags '{}' 2>&1 | awk '{ s += \$1 } END { printf (\"%d\",s) }'`;
|
||||
} elsif ($mysqlvermajor >= 5) {
|
||||
$mycalc{'total_myisam_indexes'} = `mysql $mysqllogin -Bse "SELECT IFNULL(SUM(INDEX_LENGTH),0) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema');"`;
|
||||
if ($doremote eq 0 and !mysql_version_ge(5)) {
|
||||
my $size = 0;
|
||||
$size += (split)[0] for `find $myvar{'datadir'} -name "*.MYI" 2>&1 | xargs du -L $duflags 2>&1`;
|
||||
$mycalc{'total_myisam_indexes'} = $size;
|
||||
} elsif (mysql_version_ge(5)) {
|
||||
$mycalc{'total_myisam_indexes'} = `mysql $mysqllogin -Bse "SELECT IFNULL(SUM(INDEX_LENGTH),0) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema') AND ENGINE = 'MyISAM';"`;
|
||||
}
|
||||
if (defined $mycalc{'total_myisam_indexes'} and $mycalc{'total_myisam_indexes'} =~ /^0\n$/) {
|
||||
$mycalc{'total_myisam_indexes'} = "fail";
|
||||
if (defined $mycalc{'total_myisam_indexes'} and $mycalc{'total_myisam_indexes'} == 0) {
|
||||
$mycalc{'total_myisam_indexes'} = "fail";
|
||||
} elsif (defined $mycalc{'total_myisam_indexes'}) {
|
||||
chomp($mycalc{'total_myisam_indexes'});
|
||||
}
|
||||
|
||||
|
||||
# Query cache
|
||||
if ($mysqlvermajor > 3) {
|
||||
if (mysql_version_ge(4)) {
|
||||
$mycalc{'query_cache_efficiency'} = sprintf("%.1f",($mystat{'Qcache_hits'} / ($mystat{'Com_select'} + $mystat{'Qcache_hits'})) * 100);
|
||||
if ($myvar{'query_cache_size'}) {
|
||||
$mycalc{'pct_query_cache_used'} = sprintf("%.1f",100 - ($mystat{'Qcache_free_memory'} / $myvar{'query_cache_size'}) * 100);
|
||||
|
@ -565,17 +638,17 @@ sub calculations {
|
|||
$mycalc{'query_cache_prunes_per_day'} = int($mystat{'Qcache_lowmem_prunes'} / ($mystat{'Uptime'}/86400));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Sorting
|
||||
$mycalc{'total_sorts'} = $mystat{'Sort_scan'} + $mystat{'Sort_range'};
|
||||
if ($mycalc{'total_sorts'} > 0) {
|
||||
$mycalc{'pct_temp_sort_table'} = int(($mystat{'Sort_merge_passes'} / $mycalc{'total_sorts'}) * 100);
|
||||
}
|
||||
|
||||
|
||||
# Joins
|
||||
$mycalc{'joins_without_indexes'} = $mystat{'Select_range_check'} + $mystat{'Select_full_join'};
|
||||
$mycalc{'joins_without_indexes_per_day'} = int($mycalc{'joins_without_indexes'} / ($mystat{'Uptime'}/86400));
|
||||
|
||||
|
||||
# Temporary tables
|
||||
if ($mystat{'Created_tmp_tables'} > 0) {
|
||||
if ($mystat{'Created_tmp_disk_tables'} > 0) {
|
||||
|
@ -584,19 +657,19 @@ sub calculations {
|
|||
$mycalc{'pct_temp_disk'} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Table cache
|
||||
if ($mystat{'Opened_tables'} > 0) {
|
||||
$mycalc{'table_cache_hit_rate'} = int($mystat{'Open_tables'}*100/$mystat{'Opened_tables'});
|
||||
} else {
|
||||
$mycalc{'table_cache_hit_rate'} = 100;
|
||||
}
|
||||
|
||||
|
||||
# Open files
|
||||
if ($myvar{'open_files_limit'} > 0) {
|
||||
$mycalc{'pct_files_open'} = int($mystat{'Open_files'}*100/$myvar{'open_files_limit'});
|
||||
}
|
||||
|
||||
|
||||
# Table locks
|
||||
if ($mystat{'Table_locks_immediate'} > 0) {
|
||||
if ($mystat{'Table_locks_waited'} == 0) {
|
||||
|
@ -605,7 +678,7 @@ sub calculations {
|
|||
$mycalc{'pct_table_locks_immediate'} = int($mystat{'Table_locks_immediate'}*100/($mystat{'Table_locks_waited'} + $mystat{'Table_locks_immediate'}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Thread cache
|
||||
$mycalc{'thread_cache_hit_rate'} = int(100 - (($mystat{'Threads_created'} / $mystat{'Connections'}) * 100));
|
||||
|
||||
|
@ -653,7 +726,7 @@ sub mysql_stats {
|
|||
} else {
|
||||
goodprint "Maximum possible memory usage: ".hr_bytes($mycalc{'total_possible_used_memory'})." ($mycalc{'pct_physical_memory'}% of installed RAM)\n";
|
||||
}
|
||||
|
||||
|
||||
# Slow queries
|
||||
if ($mycalc{'pct_slow_queries'} > 5) {
|
||||
badprint "Slow queries: $mycalc{'pct_slow_queries'}% (".hr_num($mystat{'Slow_queries'})."/".hr_num($mystat{'Questions'}).")\n";
|
||||
|
@ -664,7 +737,7 @@ sub mysql_stats {
|
|||
if (defined($myvar{'log_slow_queries'})) {
|
||||
if ($myvar{'log_slow_queries'} eq "OFF") { push(@generalrec,"Enable the slow query log to troubleshoot bad queries"); }
|
||||
}
|
||||
|
||||
|
||||
# Connections
|
||||
if ($mycalc{'pct_connections_used'} > 85) {
|
||||
badprint "Highest connection usage: $mycalc{'pct_connections_used'}% ($mystat{'Max_used_connections'}/$myvar{'max_connections'})\n";
|
||||
|
@ -674,11 +747,11 @@ sub mysql_stats {
|
|||
} else {
|
||||
goodprint "Highest usage of available connections: $mycalc{'pct_connections_used'}% ($mystat{'Max_used_connections'}/$myvar{'max_connections'})\n";
|
||||
}
|
||||
|
||||
|
||||
# Key buffer
|
||||
if (!defined($mycalc{'total_myisam_indexes'}) and $doremote eq 1) {
|
||||
if (!defined($mycalc{'total_myisam_indexes'}) and $doremote == 1) {
|
||||
push(@generalrec,"Unable to calculate MyISAM indexes on remote MySQL server < 5.0.0");
|
||||
} elsif ($mycalc{'total_myisam_indexes'} =~ /^fail$/) {
|
||||
} elsif ($mycalc{'total_myisam_indexes'} =~ /^fail$/) {
|
||||
badprint "Cannot calculate MyISAM index size - re-run script as root user\n";
|
||||
} elsif ($mycalc{'total_myisam_indexes'} == "0") {
|
||||
badprint "None of your MyISAM tables are indexed - add indexes immediately\n";
|
||||
|
@ -696,14 +769,12 @@ sub mysql_stats {
|
|||
goodprint "Key buffer hit rate: $mycalc{'pct_keys_from_mem'}% (".hr_num($mystat{'Key_read_requests'})." cached / ".hr_num($mystat{'Key_reads'})." reads)\n";
|
||||
}
|
||||
} else {
|
||||
# For the sake of space, we will be quiet here
|
||||
# No queries have run that would use keys
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Query cache
|
||||
if ($mysqlvermajor < 4) {
|
||||
# For the sake of space, we will be quiet here
|
||||
if (!mysql_version_ge(4)) {
|
||||
# MySQL versions < 4.01 don't support query caching
|
||||
push(@generalrec,"Upgrade MySQL to version 4+ to utilize query caching");
|
||||
} elsif ($myvar{'query_cache_size'} < 1) {
|
||||
|
@ -720,12 +791,17 @@ sub mysql_stats {
|
|||
}
|
||||
if ($mycalc{'query_cache_prunes_per_day'} > 98) {
|
||||
badprint "Query cache prunes per day: $mycalc{'query_cache_prunes_per_day'}\n";
|
||||
push(@adjvars,"query_cache_size (> ".hr_bytes_rnd($myvar{'query_cache_size'}).")")
|
||||
if ($myvar{'query_cache_size'} > 128*1024*1024) {
|
||||
push(@generalrec,"Increasing the query_cache size over 128M may reduce performance");
|
||||
push(@adjvars,"query_cache_size (> ".hr_bytes_rnd($myvar{'query_cache_size'}).") [see warning above]");
|
||||
} else {
|
||||
push(@adjvars,"query_cache_size (> ".hr_bytes_rnd($myvar{'query_cache_size'}).")");
|
||||
}
|
||||
} else {
|
||||
goodprint "Query cache prunes per day: $mycalc{'query_cache_prunes_per_day'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Sorting
|
||||
if ($mycalc{'total_sorts'} == 0) {
|
||||
# For the sake of space, we will be quiet here
|
||||
|
@ -737,7 +813,7 @@ sub mysql_stats {
|
|||
} else {
|
||||
goodprint "Sorts requiring temporary tables: $mycalc{'pct_temp_sort_table'}% (".hr_num($mystat{'Sort_merge_passes'})." temp sorts / ".hr_num($mycalc{'total_sorts'})." sorts)\n";
|
||||
}
|
||||
|
||||
|
||||
# Joins
|
||||
if ($mycalc{'joins_without_indexes_per_day'} > 250) {
|
||||
badprint "Joins performed without indexes: $mycalc{'joins_without_indexes'}\n";
|
||||
|
@ -747,7 +823,7 @@ sub mysql_stats {
|
|||
# For the sake of space, we will be quiet here
|
||||
# No joins have run without indexes
|
||||
}
|
||||
|
||||
|
||||
# Temporary tables
|
||||
if ($mystat{'Created_tmp_tables'} > 0) {
|
||||
if ($mycalc{'pct_temp_disk'} > 25 && $mycalc{'max_tmp_table_size'} < 256*1024*1024) {
|
||||
|
@ -786,7 +862,7 @@ sub mysql_stats {
|
|||
if ($mystat{'Open_tables'} > 0) {
|
||||
if ($mycalc{'table_cache_hit_rate'} < 20) {
|
||||
badprint "Table cache hit rate: $mycalc{'table_cache_hit_rate'}% (".hr_num($mystat{'Open_tables'})." open / ".hr_num($mystat{'Opened_tables'})." opened)\n";
|
||||
if ($mysqlvermajor eq 6 || ($mysqlvermajor eq 5 && $mysqlverminor ge 1)) {
|
||||
if (mysql_version_ge(5, 1)) {
|
||||
push(@adjvars,"table_cache (> ".$myvar{'table_open_cache'}.")");
|
||||
} else {
|
||||
push(@adjvars,"table_cache (> ".$myvar{'table_cache'}.")");
|
||||
|
@ -818,7 +894,7 @@ sub mysql_stats {
|
|||
}
|
||||
|
||||
# Performance options
|
||||
if ($mysqlvermajor == 3 || ($mysqlvermajor == 4 && $mysqlverminor == 0)) {
|
||||
if (!mysql_version_ge(4, 1)) {
|
||||
push(@generalrec,"Upgrade to MySQL 4.1+ to use concurrent MyISAM inserts");
|
||||
} elsif ($myvar{'concurrent_insert'} eq "OFF") {
|
||||
push(@generalrec,"Enable concurrent_insert by setting it to 'ON'");
|
||||
|
@ -829,7 +905,7 @@ sub mysql_stats {
|
|||
badprint "Connections aborted: ".$mycalc{'pct_aborted_connections'}."%\n";
|
||||
push(@generalrec,"Your applications are not closing MySQL connections properly");
|
||||
}
|
||||
|
||||
|
||||
# InnoDB
|
||||
if (defined $myvar{'have_innodb'} && $myvar{'have_innodb'} eq "YES" && defined $enginestats{'InnoDB'}) {
|
||||
if ($myvar{'innodb_buffer_pool_size'} > $enginestats{'InnoDB'}) {
|
||||
|
@ -875,9 +951,16 @@ validate_tuner_version; # Check current MySQLTuner version
|
|||
validate_mysql_version; # Check current MySQL version
|
||||
check_architecture; # Suggest 64-bit upgrade
|
||||
check_storage_engines; # Show enabled storage engines
|
||||
security_recommendations; # Display some security recommendations
|
||||
calculations; # Calculate everything we need
|
||||
mysql_stats; # Print the server stats
|
||||
make_recommendations; # Make recommendations based on stats
|
||||
# ---------------------------------------------------------------------------
|
||||
# END 'MAIN'
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Local variables:
|
||||
# indent-tabs-mode: t
|
||||
# cperl-indent-level: 8
|
||||
# perl-indent-level: 8
|
||||
# End:
|
||||
|
|
Loading…
Reference in a new issue