(#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:
Daniel Black 2012-02-04 07:08:08 +11:00
parent 2f5615688f
commit b809e6fd75

View file

@ -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: