Fixed a bug in MySQL 3.23 where the storage engine checks had problems

Adjusted some of the Perl code to be more compact, organized, and factored
This commit is contained in:
Major Hayden 2008-01-16 03:39:36 +00:00
parent 9ccae41ead
commit e693649bf9

View file

@ -34,6 +34,9 @@ use warnings;
use diagnostics; use diagnostics;
use Getopt::Long; use Getopt::Long;
# Set up a few variables for use in the script
my (@adjvars, @generalrec);
# Set defaults # Set defaults
my %opt = ( my %opt = (
"nobad" => 0, "nobad" => 0,
@ -54,6 +57,7 @@ GetOptions(\%opt,
if (defined $opt{'help'} && $opt{'help'} == 1) { usage(); } if (defined $opt{'help'} && $opt{'help'} == 1) { usage(); }
sub usage { sub usage {
# Shown with --help option passed
print "\n". print "\n".
" MySQL High Performance Tuning Script\n". " MySQL High Performance Tuning Script\n".
" Bug reports, feature requests, and downloads at http://mysqltuner.com/\n". " Bug reports, feature requests, and downloads at http://mysqltuner.com/\n".
@ -71,46 +75,81 @@ sub usage {
exit; exit;
} }
# CONFIGURATION ITEMS # Setting up the colors for the print styles
my ($good,$bad,$info); my $good = ($opt{nocolor} == 0)? "[\e[00;32mOK\e[00m]" : "[OK]" ;
if ($opt{nocolor} == 0) { my $bad = ($opt{nocolor} == 0)? "[\e[00;31mOK\e[00m]" : "[!!]" ;
$good = "[\e[00;32mOK\e[00m]"; my $info = ($opt{nocolor} == 0)? "[\e[00;34mOK\e[00m]" : "[--]" ;
$bad = "[\e[00;31m!!\e[00m]";
$info = "[\e[00;34m**\e[00m]"; # 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 "\e[00;31m".$_[0]."\e[00m"; }
sub greenwrap { return "\e[00;32m".$_[0]."\e[00m"; }
# Calculates the parameter passed in bytes, and then rounds it to one decimal place
sub hr_bytes {
my $num = shift;
if ($num >= (1024**3)) { #GB
return sprintf("%.1f",($num/(1024**3)))."G";
} elsif ($num >= (1024**2)) { #MB
return sprintf("%.1f",($num/(1024**2)))."M";
} elsif ($num >= 1024) { #KB
return sprintf("%.1f",($num/1024))."K";
} else { } else {
$good = "[OK]"; return $num."B";
$bad = "[!!]"; }
$info = "[--]";
} }
sub goodprint { # Calculates the parameter passed in bytes, and then rounds it to the nearest integer
if ($opt{nogood} == 1) { return 0; } sub hr_bytes_rnd {
my $text = shift; my $num = shift;
print $good." ".$text; if ($num >= (1024**3)) { #GB
return int(($num/(1024**3)))."G";
} elsif ($num >= (1024**2)) { #MB
return int(($num/(1024**2)))."M";
} elsif ($num >= 1024) { #KB
return int(($num/1024))."K";
} else {
return $num."B";
}
} }
sub infoprint { # Calculates the parameter passed to the nearest power of 1000, then rounds it to the nearest integer
if ($opt{noinfo} == 1) { return 0; } sub hr_num {
my $text = shift; my $num = shift;
print $info." ".$text; if ($num >= (1000**3)) { # Billions
return int(($num/(1000**3)))."B";
} elsif ($num >= (1000**2)) { # Millions
return int(($num/(1000**2)))."M";
} elsif ($num >= 1000) { # Thousands
return int(($num/1000))."K";
} else {
return $num;
}
} }
sub badprint { # Calculates uptime to display in a more attractive form
if ($opt{nobad} == 1) { return 0; } sub pretty_uptime {
my $text = shift; my $uptime = shift;
print $bad." ".$text; my $seconds = $uptime % 60;
} my $minutes = int(($uptime % 3600) / 60);
my $hours = int(($uptime % 86400) / (3600));
sub redwrap { my $days = int($uptime / (86400));
my $text = shift; my $uptimestring;
return "\e[00;31m".$text."\e[00m"; if ($days > 0) {
} $uptimestring = "${days}d ${hours}h ${minutes}m ${seconds}s";
} elsif ($hours > 0) {
sub greenwrap { $uptimestring = "${hours}h ${minutes}m ${seconds}s";
my $text = shift; } elsif ($minutes > 0) {
return "\e[00;32m".$text."\e[00m"; $uptimestring = "${minutes}m ${seconds}s";
} else {
$uptimestring = "${seconds}s";
}
return $uptimestring;
} }
# Retrieves the memory installed on this machine
my ($physical_memory,$swap_memory,$duflags); my ($physical_memory,$swap_memory,$duflags);
sub os_setup { sub os_setup {
my $os = `uname`; my $os = `uname`;
@ -132,6 +171,7 @@ sub os_setup {
chomp($physical_memory); chomp($physical_memory);
} }
# Checks to see if a MySQL login is possible
my $mysqllogin; my $mysqllogin;
sub mysql_setup { sub mysql_setup {
my $command = `which mysqladmin`; my $command = `which mysqladmin`;
@ -144,10 +184,7 @@ sub mysql_setup {
# It's a Plesk box, use the available credentials # It's a Plesk box, use the available credentials
$mysqllogin = "-u admin -p`cat /etc/psa/.psa.shadow`"; $mysqllogin = "-u admin -p`cat /etc/psa/.psa.shadow`";
my $loginstatus = `mysqladmin ping $mysqllogin 2>&1`; my $loginstatus = `mysqladmin ping $mysqllogin 2>&1`;
if ($loginstatus =~ /mysqld is alive/) { unless ($loginstatus =~ /mysqld is alive/) {
# Login was successful, but we won't say anything to save space
return 1;
} else {
badprint "Attempted to use login credentials from Plesk, but they failed.\n"; badprint "Attempted to use login credentials from Plesk, but they failed.\n";
exit 0; exit 0;
} }
@ -160,16 +197,14 @@ sub mysql_setup {
# Did this go well because of a .my.cnf file or is there no password set? # Did this go well because of a .my.cnf file or is there no password set?
my $userpath = `ls -d ~`; my $userpath = `ls -d ~`;
chomp($userpath); chomp($userpath);
if ( -e "$userpath/.my.cnf" ) { unless ( -e "$userpath/.my.cnf" ) {
# Login was successful, but we won't say anything to save space
} else {
badprint "Successfully authenticated with no password - SECURITY RISK!\n"; badprint "Successfully authenticated with no password - SECURITY RISK!\n";
} }
return 1; return 1;
} else { } else {
print STDERR "Please enter your MySQL login: "; print STDERR "Please enter your MySQL administrative login: ";
my $name = <>; my $name = <>;
print STDERR "Please enter your MySQL password: "; print STDERR "Please enter your MySQL administrative password: ";
system("stty -echo"); system("stty -echo");
my $password = <>; my $password = <>;
system("stty echo"); system("stty echo");
@ -178,7 +213,6 @@ sub mysql_setup {
$mysqllogin = "-u $name -p'$password'"; $mysqllogin = "-u $name -p'$password'";
my $loginstatus = `mysqladmin ping $mysqllogin 2>&1`; my $loginstatus = `mysqladmin ping $mysqllogin 2>&1`;
if ($loginstatus =~ /mysqld is alive/) { if ($loginstatus =~ /mysqld is alive/) {
# Login was successful, but we won't say anything to save space
print STDERR "\n"; print STDERR "\n";
return 1; return 1;
} else { } else {
@ -190,6 +224,7 @@ sub mysql_setup {
} }
} }
# Populates all of the variable and status hashes
my (%mystat,%myvar,$dummyselect); my (%mystat,%myvar,$dummyselect);
sub get_all_vars { sub get_all_vars {
# We need to initiate at least one query so that our data is useable # We need to initiate at least one query so that our data is useable
@ -206,6 +241,7 @@ sub get_all_vars {
} }
} }
# Checks for supported or EOL'ed MySQL versions
my ($mysqlvermajor,$mysqlverminor); my ($mysqlvermajor,$mysqlverminor);
sub validate_mysql_version { sub validate_mysql_version {
print "-------- General Statistics --------------------------------------------------\n"; print "-------- General Statistics --------------------------------------------------\n";
@ -219,6 +255,7 @@ sub validate_mysql_version {
} }
} }
# Checks for 32-bit boxes with more than 2GB of RAM
my ($arch); my ($arch);
sub check_architecture { sub check_architecture {
if (`uname -m` =~ /64/) { if (`uname -m` =~ /64/) {
@ -226,7 +263,7 @@ sub check_architecture {
goodprint "Operating on 64-bit architecture\n"; goodprint "Operating on 64-bit architecture\n";
} else { } else {
$arch = 32; $arch = 32;
if ($physical_memory > 2*1024*1024*1024) { if ($physical_memory > 2147483648) {
badprint "Switch to 64-bit OS - MySQL cannot currenty use all of your RAM\n"; badprint "Switch to 64-bit OS - MySQL cannot currenty use all of your RAM\n";
} else { } else {
goodprint "Operating on 32-bit architecture with less than 2GB RAM\n"; goodprint "Operating on 32-bit architecture with less than 2GB RAM\n";
@ -234,7 +271,8 @@ sub check_architecture {
} }
} }
my %enginestats; # Start up a ton of storage engine counts/statistics
my (%enginestats,%enginecount);
sub check_storage_engines { sub check_storage_engines {
print "-------- Storage Engine Statistics -------------------------------------------\n"; print "-------- Storage Engine Statistics -------------------------------------------\n";
infoprint "Status: "; infoprint "Status: ";
@ -247,90 +285,47 @@ sub check_storage_engines {
$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"; print "$engines\n";
my @tblist; my @tblist;
# Now we build a database list, and loop through it to get storage engine stats for tables
my @dblist = `mysql $mysqllogin -Bse "SHOW DATABASES"`; my @dblist = `mysql $mysqllogin -Bse "SHOW DATABASES"`;
foreach my $db (@dblist) { foreach my $db (@dblist) {
chomp($db); chomp($db);
if ($mysqlvermajor == 3) {
# MySQL 3.23 keeps Data_Length in the 6th column
push (@tblist,`mysql $mysqllogin -Bse "SHOW TABLE STATUS FROM \\\`$db\\\`" | awk '{print \$2,\$6}'`);
} else {
# MySQL 4.0+ keeps Data_Length in the 7th column
push (@tblist,`mysql $mysqllogin -Bse "SHOW TABLE STATUS FROM \\\`$db\\\`" | awk '{print \$2,\$7}'`); push (@tblist,`mysql $mysqllogin -Bse "SHOW TABLE STATUS FROM \\\`$db\\\`" | awk '{print \$2,\$7}'`);
}
}
# Parse through the table list to generate storage engine counts/statistics
foreach my $line (@tblist) { foreach my $line (@tblist) {
$line =~ /([a-zA-Z_]*)\s*(.*)/; $line =~ /([a-zA-Z_]*)\s*(.*)/;
my $engine = $1; my $engine = $1;
my $size = $2; my $size = $2;
if ($size !~ /^\d+$/) { if ($size !~ /^\d+$/) { $size = 0; }
$size = 0;
}
if (defined $enginestats{$engine}) { if (defined $enginestats{$engine}) {
$enginestats{$engine} = $enginestats{$engine} + $size; $enginestats{$engine} += $size;
$enginecount{$engine} += 1;
} else { } else {
$enginestats{$engine} = $size; $enginestats{$engine} = $size;
} $enginecount{$engine} = 1;
} }
} }
while (my ($engine,$size) = each(%enginestats)) { while (my ($engine,$size) = each(%enginestats)) {
infoprint "Data in $engine tables: ".hr_bytes_rnd($size)."\n"; infoprint "Data in $engine tables: ".hr_bytes_rnd($size)." (Tables: ".$enginecount{$engine}.")"."\n";
} }
# If the storage engine isn't being used, recommend it to be disabled
if (!defined $enginestats{'InnoDB'} && defined $myvar{'have_innodb'} && $myvar{'have_innodb'} eq "YES") { if (!defined $enginestats{'InnoDB'} && defined $myvar{'have_innodb'} && $myvar{'have_innodb'} eq "YES") {
badprint "InnoDB is enabled but isn't being used\n"; badprint "InnoDB is enabled but isn't being used\n";
push(@generalrec,"Add skip-innodb to MySQL configuration to disable InnoDB");
} }
if (!defined $enginestats{'BDB'} && defined $myvar{'have_bdb'} && $myvar{'have_bdb'} eq "YES") { if (!defined $enginestats{'BDB'} && defined $myvar{'have_bdb'} && $myvar{'have_bdb'} eq "YES") {
badprint "BDB is enabled but isn't being used\n"; badprint "BDB is enabled but isn't being used\n";
push(@generalrec,"Add skip-bdb to MySQL configuration to disable BDB");
} }
} if (!defined $enginestats{'ISAM'} && defined $myvar{'have_isam'} && $myvar{'have_isam'} eq "YES") {
badprint "ISAM is enabled but isn't being used\n";
sub pretty_uptime { push(@generalrec,"Add skip-isam to MySQL configuration to disable ISAM");
my $uptime = shift;
my $seconds = $uptime % 60;
my $minutes = int(($uptime % 3600) / 60);
my $hours = int(($uptime % 86400) / (3600));
my $days = int($uptime / (86400));
my $uptimestring;
if ($days > 0) {
$uptimestring = "${days}d ${hours}h ${minutes}m ${seconds}s";
} elsif ($hours > 0) {
$uptimestring = "${hours}h ${minutes}m ${seconds}s";
} elsif ($minutes > 0) {
$uptimestring = "${minutes}m ${seconds}s";
} else {
$uptimestring = "${seconds}s";
}
return $uptimestring;
}
sub hr_bytes_rnd {
my $num = shift;
if ($num >= (1024**3)) { #GB
return int(($num/(1024**3)))."G";
} elsif ($num >= (1024**2)) { #MB
return int(($num/(1024**2)))."M";
} elsif ($num >= 1024) { #KB
return int(($num/1024))."K";
} else {
return $num."B";
}
}
sub hr_bytes {
my $num = shift;
if ($num >= (1024**3)) { #GB
return sprintf("%.1f",($num/(1024**3)))."G";
} elsif ($num >= (1024**2)) { #MB
return sprintf("%.1f",($num/(1024**2)))."M";
} elsif ($num >= 1024) { #KB
return sprintf("%.1f",($num/1024))."K";
} else {
return $num."B";
}
}
sub hr_num {
my $num = shift;
if ($num >= (1000**3)) { #GB
return int(($num/(1000**3)))."G";
} elsif ($num >= (1000**2)) { #MB
return int(($num/(1000**2)))."M";
} elsif ($num >= 1000) { #KB
return int(($num/1000))."K";
} else {
return $num;
} }
} }
@ -458,7 +453,7 @@ sub calculations {
} }
} }
my (@adjvars, @generalrec); #my (@adjvars, @generalrec);
sub mysql_stats { sub mysql_stats {
print "-------- Performance Metrics -------------------------------------------------\n"; print "-------- Performance Metrics -------------------------------------------------\n";
# Show uptime, queries per second, connections, traffic stats # Show uptime, queries per second, connections, traffic stats
@ -663,6 +658,7 @@ sub mysql_stats {
} }
} }
# Take the two recommendation arrays and display them at the end of the output
sub make_recommendations { sub make_recommendations {
print "-------- Recommendations -----------------------------------------------------\n"; print "-------- Recommendations -----------------------------------------------------\n";
if (@generalrec > 0) { if (@generalrec > 0) {