Merge pull request #701 from jmrenouard/master

Update code and CVEs
This commit is contained in:
Jean-Marie Renouard 2023-07-06 08:24:00 +02:00 committed by GitHub
commit c5e5c81266
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 317 additions and 233 deletions

View file

@ -26,6 +26,7 @@ Features list for option: --feature (dev only)
* mysql_routines * mysql_routines
* mysql_setup * mysql_setup
* mysql_stats * mysql_stats
* mysql_table_structures
* mysql_tables * mysql_tables
* mysql_triggers * mysql_triggers
* mysql_version_eq * mysql_version_eq

View file

@ -1,6 +1,6 @@
# NAME # NAME
MySQLTuner 2.1.5 - MySQL High Performance Tuning Script MySQLTuner 2.2.5 - MySQL High Performance Tuning Script
# IMPORTANT USAGE GUIDELINES # IMPORTANT USAGE GUIDELINES
@ -62,8 +62,10 @@ You must provide the remote server's total memory when connecting to other serve
--nocolstat Don't print column information --nocolstat Don't print column information
--idxstat Print index information --idxstat Print index information
--noidxstat Don't print index information --noidxstat Don't print index information
--nomyisamstat Don't print MyIsam information
--sysstat Print system information --sysstat Print system information
--nosysstat Don't print system information --nosysstat Don't print system information
--nostructstat Don't print table structures information
--pfstat Print Performance schema --pfstat Print Performance schema
--nopfstat Don't print Performance schema --nopfstat Don't print Performance schema
--bannedports Ports banned separated by comma (,) --bannedports Ports banned separated by comma (,)

View file

@ -1,5 +1,5 @@
#!/usr/bin/env perl #!/usr/bin/env perl
# mysqltuner.pl - Version 2.2.5 # mysqltuner.pl - Version 2.2.6
# High Performance MySQL Tuning Script # High Performance MySQL Tuning Script
# Copyright (C) 2006-2023 Major Hayden - major@mhtx.net # Copyright (C) 2006-2023 Major Hayden - major@mhtx.net
# Copyright (C) 2015-2023 Jean-Marie Renouard - jmrenouard@gmail.com # Copyright (C) 2015-2023 Jean-Marie Renouard - jmrenouard@gmail.com
@ -57,7 +57,7 @@ use Cwd 'abs_path';
#use Env; #use Env;
# Set up a few variables for use in the script # Set up a few variables for use in the script
my $tunerversion = "2.2.5"; my $tunerversion = "2.2.6";
my ( @adjvars, @generalrec ); my ( @adjvars, @generalrec );
# Set defaults # Set defaults
@ -208,6 +208,7 @@ $basic_password_files = "/usr/share/mysqltuner/basic_passwords.txt"
unless -f "$basic_password_files"; unless -f "$basic_password_files";
$opt{dbgpattern} = '.*' if ( $opt{dbgpattern} eq '' ); $opt{dbgpattern} = '.*' if ( $opt{dbgpattern} eq '' );
# check if we need to enable verbose mode # check if we need to enable verbose mode
if ( $opt{feature} ne '' ) { $opt{verbose} = 1; } if ( $opt{feature} ne '' ) { $opt{verbose} = 1; }
if ( $opt{verbose} ) { if ( $opt{verbose} ) {
@ -233,8 +234,10 @@ $opt{sysstat} = 0 if ( $opt{nosysstat} == 1 ); # Don't print sysstat information
$opt{pfstat} = 0 $opt{pfstat} = 0
if ( $opt{nopfstat} == 1 ); # Don't print performance schema information if ( $opt{nopfstat} == 1 ); # Don't print performance schema information
$opt{idxstat} = 0 if ( $opt{noidxstat} == 1 ); # Don't print index information $opt{idxstat} = 0 if ( $opt{noidxstat} == 1 ); # Don't print index information
$opt{structstat} = 0 if ( $opt{nostructstat} == 1 ); # Don't print table struct information $opt{structstat} = 0
$opt{myisamstat} = 0 if ( $opt{nomyisamstat} == 1 ); # Don't print MyISAM table information if ( $opt{nostructstat} == 1 ); # Don't print table struct information
$opt{myisamstat} = 0
if ( $opt{nomyisamstat} == 1 ); # Don't print MyISAM table information
# for RPM distributions # for RPM distributions
$opt{cvefile} = "/usr/share/mysqltuner/vulnerabilities.csv" $opt{cvefile} = "/usr/share/mysqltuner/vulnerabilities.csv"
@ -347,9 +350,11 @@ sub is_remote() {
return 0 if ( $host eq '127.0.0.1' ); return 0 if ( $host eq '127.0.0.1' );
return 1; return 1;
} }
sub is_int { sub is_int {
return 0 unless defined $_[0]; return 0 unless defined $_[0];
my $str = $_[0]; my $str = $_[0];
#trim whitespace both sides #trim whitespace both sides
$str =~ s/^\s+|\s+$//g; $str =~ s/^\s+|\s+$//g;
@ -362,6 +367,7 @@ sub is_int {
} }
return 0; return 0;
} }
# Calculates the number of physical cores considering HyperThreading # Calculates the number of physical cores considering HyperThreading
sub cpu_cores { sub cpu_cores {
if ( $^O eq 'linux' ) { if ( $^O eq 'linux' ) {
@ -769,6 +775,7 @@ sub mysql_setup {
elsif ( !-e $mysqladmincmd ) { elsif ( !-e $mysqladmincmd ) {
badprint badprint
"Couldn't find mysqladmin/mariadb-admin in your \$PATH. Is MySQL installed?"; "Couldn't find mysqladmin/mariadb-admin in your \$PATH. Is MySQL installed?";
#exit 1; #exit 1;
} }
if ( $opt{mysqlcmd} ) { if ( $opt{mysqlcmd} ) {
@ -820,14 +827,19 @@ sub mysql_setup {
# If we're doing a remote connection, but forcemem wasn't specified, we need to exit # If we're doing a remote connection, but forcemem wasn't specified, we need to exit
if ( $opt{'forcemem'} eq 0 && is_remote eq 1 ) { if ( $opt{'forcemem'} eq 0 && is_remote eq 1 ) {
badprint "The --forcemem option is required for remote connections"; badprint "The --forcemem option is required for remote connections";
badprint "Assuming RAM memory is 1Gb for simplify remote connection usage"; badprint
"Assuming RAM memory is 1Gb for simplify remote connection usage";
$opt{'forcemem'} = 1024; $opt{'forcemem'} = 1024;
#exit 1; #exit 1;
} }
if ( $opt{'forceswap'} eq 0 && is_remote eq 1 ) { if ( $opt{'forceswap'} eq 0 && is_remote eq 1 ) {
badprint "The --forceswap option is required for remote connections"; badprint
badprint "Assuming Swap size is 1Gb for simplify remote connection usage"; "The --forceswap option is required for remote connections";
badprint
"Assuming Swap size is 1Gb for simplify remote connection usage";
$opt{'forceswap'} = 1024; $opt{'forceswap'} = 1024;
#exit 1; #exit 1;
} }
infoprint "Performing tests on $opt{host}:$opt{port}"; infoprint "Performing tests on $opt{host}:$opt{port}";
@ -859,7 +871,8 @@ sub mysql_setup {
"-u $opt{user} " "-u $opt{user} "
. ( ( $opt{pass} ne 0 ) ? "-p'$opt{pass}' " : " " ) . ( ( $opt{pass} ne 0 ) ? "-p'$opt{pass}' " : " " )
. $remotestring; . $remotestring;
my $loginstatus = `$mysqlcmd -Nrs -e 'select "mysqld is alive";' $mysqllogin 2>&1`; my $loginstatus =
`$mysqlcmd -Nrs -e 'select "mysqld is alive";' $mysqllogin 2>&1`;
if ( $loginstatus =~ /mysqld is alive/ ) { if ( $loginstatus =~ /mysqld is alive/ ) {
goodprint "Logged in using credentials passed on the command line"; goodprint "Logged in using credentials passed on the command line";
return 1; return 1;
@ -994,12 +1007,15 @@ sub mysql_setup {
#my $loginstatus = ""; #my $loginstatus = "";
debugprint "Using mysqlcmd: $mysqlcmd"; debugprint "Using mysqlcmd: $mysqlcmd";
#if (defined($mysqladmincmd)) { #if (defined($mysqladmincmd)) {
# infoprint "Using mysqladmin to check login"; # infoprint "Using mysqladmin to check login";
# $loginstatus=`$mysqladmincmd $remotestring ping 2>&1`; # $loginstatus=`$mysqladmincmd $remotestring ping 2>&1`;
#} else { #} else {
infoprint "Using mysql to check login"; infoprint "Using mysql to check login";
my $loginstatus=`$mysqlcmd $remotestring -Nrs -e 'select "mysqld is alive"' --connect-timeout=3 2>&1`; my $loginstatus =
`$mysqlcmd $remotestring -Nrs -e 'select "mysqld is alive"' --connect-timeout=3 2>&1`;
#} #}
if ( $loginstatus =~ /mysqld is alive/ ) { if ( $loginstatus =~ /mysqld is alive/ ) {
@ -1126,6 +1142,7 @@ sub select_csv_file {
my $tfile = shift; my $tfile = shift;
my $req = shift; my $req = shift;
debugprint "PERFORM: $req CSV into $tfile"; debugprint "PERFORM: $req CSV into $tfile";
#return; #return;
my @result = select_array_with_headers($req); my @result = select_array_with_headers($req);
open( my $fh, '>', $tfile ) or die "Could not open file '$tfile' $!"; open( my $fh, '>', $tfile ) or die "Could not open file '$tfile' $!";
@ -1995,20 +2012,25 @@ sub system_recommendations {
#prettyprint '-'x78; #prettyprint '-'x78;
get_system_info(); get_system_info();
my $nb_cpus = cpu_cores; my $nb_cpus = cpu_cores;
if ( $nb_cpus > 1 ) { if ( $nb_cpus > 1 ) {
goodprint "There is at least one CPU dedicated to database server."; goodprint "There is at least one CPU dedicated to database server.";
} else { }
badprint "There is only one CPU, consider dedicated one CPU for your database server"; else {
push @generalrec, "Consider increasing number of CPU for your database server"; badprint
"There is only one CPU, consider dedicated one CPU for your database server";
push @generalrec,
"Consider increasing number of CPU for your database server";
} }
if ( $physical_memory < 1600 ) { if ( $physical_memory < 1600 ) {
goodprint "There is at least 1 Gb of RAM dedicated to Linux server."; goodprint "There is at least 1 Gb of RAM dedicated to Linux server.";
} else { }
badprint "There is less than 1,5 Gb of RAM, consider dedicated 1 Gb for your Linux server"; else {
push @generalrec, "Consider increasing 1,5 / 2 Gb of RAM for your Linux server"; badprint
"There is less than 1,5 Gb of RAM, consider dedicated 1 Gb for your Linux server";
push @generalrec,
"Consider increasing 1,5 / 2 Gb of RAM for your Linux server";
} }
my $omem = get_other_process_memory; my $omem = get_other_process_memory;
@ -2610,6 +2632,7 @@ sub check_storage_engines {
$result{'Engine'}{$engine}{'Data Size'} = $dsize; $result{'Engine'}{$engine}{'Data Size'} = $dsize;
$result{'Engine'}{$engine}{'Index Size'} = $isize; $result{'Engine'}{$engine}{'Index Size'} = $isize;
} }
#print Dumper( \%enginestats ) if $opt{debug}; #print Dumper( \%enginestats ) if $opt{debug};
my $not_innodb = ''; my $not_innodb = '';
if ( not defined $result{'Variables'}{'innodb_file_per_table'} ) { if ( not defined $result{'Variables'}{'innodb_file_per_table'} ) {
@ -2796,6 +2819,7 @@ sub dump_into_file {
infoprint "Data saved to $file"; infoprint "Data saved to $file";
} }
} }
sub calculations { sub calculations {
if ( $mystat{'Questions'} < 1 ) { if ( $mystat{'Questions'} < 1 ) {
badprint "Your server has not answered any queries: cannot continue..."; badprint "Your server has not answered any queries: cannot continue...";
@ -2804,13 +2828,20 @@ sub calculations {
# Per-thread memory # Per-thread memory
$mycalc{'per_thread_buffers'} = 0; $mycalc{'per_thread_buffers'} = 0;
$mycalc{'per_thread_buffers'} += $myvar{'read_buffer_size'} if is_int($myvar{'read_buffer_size'}); $mycalc{'per_thread_buffers'} += $myvar{'read_buffer_size'}
$mycalc{'per_thread_buffers'} += $myvar{'read_rnd_buffer_size'} if is_int($myvar{'read_rnd_buffer_size'}); if is_int( $myvar{'read_buffer_size'} );
$mycalc{'per_thread_buffers'} += $myvar{'sort_buffer_size'} if is_int($myvar{'sort_buffer_size'}); $mycalc{'per_thread_buffers'} += $myvar{'read_rnd_buffer_size'}
$mycalc{'per_thread_buffers'} += $myvar{'thread_stack'} if is_int($myvar{'thread_stack'}); if is_int( $myvar{'read_rnd_buffer_size'} );
$mycalc{'per_thread_buffers'} += $myvar{'join_buffer_size'} if is_int($myvar{'join_buffer_size'}); $mycalc{'per_thread_buffers'} += $myvar{'sort_buffer_size'}
$mycalc{'per_thread_buffers'} += $myvar{'binlog_cache_size'} if is_int($myvar{'binlog_cache_size'}); if is_int( $myvar{'sort_buffer_size'} );
debugprint "per_thread_buffers: $mycalc{'per_thread_buffers'} (" .human_size($mycalc{'per_thread_buffers'} ) ." )"; $mycalc{'per_thread_buffers'} += $myvar{'thread_stack'}
if is_int( $myvar{'thread_stack'} );
$mycalc{'per_thread_buffers'} += $myvar{'join_buffer_size'}
if is_int( $myvar{'join_buffer_size'} );
$mycalc{'per_thread_buffers'} += $myvar{'binlog_cache_size'}
if is_int( $myvar{'binlog_cache_size'} );
debugprint "per_thread_buffers: $mycalc{'per_thread_buffers'} ("
. human_size( $mycalc{'per_thread_buffers'} ) . " )";
# Error max_allowed_packet is not included in thread buffers size # Error max_allowed_packet is not included in thread buffers size
#$mycalc{'per_thread_buffers'} += $myvar{'max_allowed_packet'} if is_int($myvar{'max_allowed_packet'}); #$mycalc{'per_thread_buffers'} += $myvar{'max_allowed_packet'} if is_int($myvar{'max_allowed_packet'});
@ -3119,7 +3150,8 @@ sub calculations {
# InnoDB # InnoDB
$myvar{'innodb_log_files_in_group'} = 1 $myvar{'innodb_log_files_in_group'} = 1
unless defined( $myvar{'innodb_log_files_in_group'} ); unless defined( $myvar{'innodb_log_files_in_group'} );
$myvar{'innodb_log_files_in_group'} = 1 if $myvar{'innodb_log_files_in_group'} == 0; $myvar{'innodb_log_files_in_group'} = 1
if $myvar{'innodb_log_files_in_group'} == 0;
$myvar{"innodb_buffer_pool_instances"} = 1 $myvar{"innodb_buffer_pool_instances"} = 1
unless defined( $myvar{'innodb_buffer_pool_instances'} ); unless defined( $myvar{'innodb_buffer_pool_instances'} );
@ -3378,7 +3410,8 @@ sub mysql_stats {
} }
# name resolution # name resolution
debugprint "skip name resolve: $result{'Variables'}{'skip_name_resolve'}" if ( defined( $result{'Variables'}{'skip_name_resolve'} ) ); debugprint "skip name resolve: $result{'Variables'}{'skip_name_resolve'}"
if ( defined( $result{'Variables'}{'skip_name_resolve'} ) );
if ( defined( $result{'Variables'}{'skip_networking'} ) if ( defined( $result{'Variables'}{'skip_networking'} )
&& $result{'Variables'}{'skip_networking'} eq 'ON' ) && $result{'Variables'}{'skip_networking'} eq 'ON' )
{ {
@ -3827,24 +3860,37 @@ sub mysql_myisam {
return 0 unless $opt{'myisamstat'} == 1; return 0 unless $opt{'myisamstat'} == 1;
subheaderprint "MyISAM Metrics"; subheaderprint "MyISAM Metrics";
my $nb_myisam_tables = select_one( my $nb_myisam_tables = select_one(
"SELECT COUNT(*) FROM information_schema.TABLES WHERE ENGINE='MyISAM' and TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema')"); "SELECT COUNT(*) FROM information_schema.TABLES WHERE ENGINE='MyISAM' and TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema')"
push (@generalrec, "MyISAM engine is deprecated, consider migrating to InnoDB") if $nb_myisam_tables > 0; );
push( @generalrec,
"MyISAM engine is deprecated, consider migrating to InnoDB" )
if $nb_myisam_tables > 0;
if ( $nb_myisam_tables > 0 ) { if ( $nb_myisam_tables > 0 ) {
badprint "Consider migrating $nb_myisam_tables followning tables to InnoDB:"; badprint
"Consider migrating $nb_myisam_tables followning tables to InnoDB:";
my $sql_mig = ""; my $sql_mig = "";
for my $myisam_table ( select_array("SELECT CONCAT(TABLE_SCHEMA, '.', TABLE_NAME) FROM information_schema.TABLES WHERE ENGINE='MyISAM' and TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema')" )) { for my $myisam_table (
$sql_mig="${sql_mig}-- InnoDB migration for $myisam_table\nALTER TABLE $myisam_table ENGINE=InnoDB;\n\n"; select_array(
infoprint "* InnoDB migration request for $myisam_table Table: ALTER TABLE $myisam_table ENGINE=InnoDB;"; "SELECT CONCAT(TABLE_SCHEMA, '.', TABLE_NAME) FROM information_schema.TABLES WHERE ENGINE='MyISAM' and TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema')"
)
)
{
$sql_mig =
"${sql_mig}-- InnoDB migration for $myisam_table\nALTER TABLE $myisam_table ENGINE=InnoDB;\n\n";
infoprint
"* InnoDB migration request for $myisam_table Table: ALTER TABLE $myisam_table ENGINE=InnoDB;";
} }
dump_into_file( "migrate_myisam_to_innodb.sql", $sql_mig ); dump_into_file( "migrate_myisam_to_innodb.sql", $sql_mig );
} }
infoprint("General MyIsam metrics:"); infoprint("General MyIsam metrics:");
infoprint " +-- Total MyISAM Tables : $nb_myisam_tables"; infoprint " +-- Total MyISAM Tables : $nb_myisam_tables";
infoprint " +-- Total MyISAM indexes : " infoprint " +-- Total MyISAM indexes : "
. hr_bytes( $mycalc{'total_myisam_indexes'} ) if defined($mycalc{'total_myisam_indexes'}); . hr_bytes( $mycalc{'total_myisam_indexes'} )
if defined( $mycalc{'total_myisam_indexes'} );
infoprint " +-- KB Size :" . hr_bytes( $myvar{'key_buffer_size'} ); infoprint " +-- KB Size :" . hr_bytes( $myvar{'key_buffer_size'} );
infoprint " +-- KB Used Size :" .hr_bytes( $myvar{'key_buffer_size'} - infoprint " +-- KB Used Size :"
. hr_bytes( $myvar{'key_buffer_size'} -
$mystat{'Key_blocks_unused'} * $myvar{'key_cache_block_size'} ); $mystat{'Key_blocks_unused'} * $myvar{'key_cache_block_size'} );
infoprint " +-- KB used :" . $mycalc{'pct_key_buffer_used'} . "%"; infoprint " +-- KB used :" . $mycalc{'pct_key_buffer_used'} . "%";
infoprint " +-- Read KB hit rate: $mycalc{'pct_keys_from_mem'}% (" infoprint " +-- Read KB hit rate: $mycalc{'pct_keys_from_mem'}% ("
@ -3873,12 +3919,14 @@ sub mysql_myisam {
} }
if ( !defined( $mycalc{'total_myisam_indexes'} ) ) { if ( !defined( $mycalc{'total_myisam_indexes'} ) ) {
badprint "Unable to calculate MyISAM index size on MySQL server < 5.0.0"; badprint
"Unable to calculate MyISAM index size on MySQL server < 5.0.0";
push( @generalrec, push( @generalrec,
"Unable to calculate MyISAM index size on MySQL server < 5.0.0" ); "Unable to calculate MyISAM index size on MySQL server < 5.0.0" );
return; return;
} }
if ( $mycalc{'pct_key_buffer_used'} == 0 ) { if ( $mycalc{'pct_key_buffer_used'} == 0 ) {
# No queries have run that would use keys # No queries have run that would use keys
infoprint "Key buffer used: $mycalc{'pct_key_buffer_used'}% (" infoprint "Key buffer used: $mycalc{'pct_key_buffer_used'}% ("
. hr_bytes( $myvar{'key_buffer_size'} - . hr_bytes( $myvar{'key_buffer_size'} -
@ -3887,15 +3935,14 @@ sub mysql_myisam {
. hr_bytes( $myvar{'key_buffer_size'} ) . hr_bytes( $myvar{'key_buffer_size'} )
. " cache)"; . " cache)";
infoprint "No SQL statement based on MyISAM table(s) detected ...."; infoprint "No SQL statement based on MyISAM table(s) detected ....";
return return;
} }
# Key buffer usage # Key buffer usage
if ( $mycalc{'pct_key_buffer_used'} < 90 ) { if ( $mycalc{'pct_key_buffer_used'} < 90 ) {
badprint "Key buffer used: $mycalc{'pct_key_buffer_used'}% (" badprint "Key buffer used: $mycalc{'pct_key_buffer_used'}% ("
. hr_bytes( $myvar{'key_buffer_size'} - . hr_bytes( $myvar{'key_buffer_size'} -
$mystat{'Key_blocks_unused'} * $myvar{'key_cache_block_size'} $mystat{'Key_blocks_unused'} * $myvar{'key_cache_block_size'} )
)
. " used / " . " used / "
. hr_bytes( $myvar{'key_buffer_size'} ) . hr_bytes( $myvar{'key_buffer_size'} )
. " cache)"; . " cache)";
@ -3904,16 +3951,16 @@ sub mysql_myisam {
@adjvars, @adjvars,
"key_buffer_size (\~ " "key_buffer_size (\~ "
. hr_num( . hr_num(
$myvar{'key_buffer_size'} * $mycalc{'pct_key_buffer_used'} $myvar{'key_buffer_size'} *
/ 100 $mycalc{'pct_key_buffer_used'} / 100
) )
. ")" . ")"
); );
} else { }
else {
goodprint "Key buffer used: $mycalc{'pct_key_buffer_used'}% (" goodprint "Key buffer used: $mycalc{'pct_key_buffer_used'}% ("
. hr_bytes( $myvar{'key_buffer_size'} - . hr_bytes( $myvar{'key_buffer_size'} -
$mystat{'Key_blocks_unused'} * $myvar{'key_cache_block_size'} $mystat{'Key_blocks_unused'} * $myvar{'key_cache_block_size'} )
)
. " used / " . " used / "
. hr_bytes( $myvar{'key_buffer_size'} ) . hr_bytes( $myvar{'key_buffer_size'} )
. " cache)"; . " cache)";
@ -3976,7 +4023,8 @@ sub mysql_myisam {
. hr_num( $mystat{'Key_writes'} ) . hr_num( $mystat{'Key_writes'} )
. " writes)"; . " writes)";
} }
} else { }
else {
# No queries have run that would use keys # No queries have run that would use keys
debugprint debugprint
"Write Key buffer hit rate: $mycalc{'pct_wkeys_from_mem'}% (" "Write Key buffer hit rate: $mycalc{'pct_wkeys_from_mem'}% ("
@ -4127,12 +4175,11 @@ sub mysql_pfs {
infoprint "Dumping $sys_view into $opt{dumpdir}"; infoprint "Dumping $sys_view into $opt{dumpdir}";
my $sys_view_table = $sys_view; my $sys_view_table = $sys_view;
$sys_view_table =~ s/\$/\\\$/g; $sys_view_table =~ s/\$/\\\$/g;
select_csv_file( select_csv_file( "$opt{dumpdir}/sys_$sys_view.csv",
"$opt{dumpdir}/sys_$sys_view.csv", 'select * from sys.\`' . $sys_view_table . '\`' );
'select * from sys.\`' . $sys_view_table. '\`'
);
} }
return; return;
#exit 0 if ( $opt{stop} == 1 ); #exit 0 if ( $opt{stop} == 1 );
} }
@ -5805,13 +5852,16 @@ and table_schema not in
"Ensure that all table(s) are InnoDB tables for performance and also for replication"; "Ensure that all table(s) are InnoDB tables for performance and also for replication";
foreach my $badtable (@nonInnoDBTables) { foreach my $badtable (@nonInnoDBTables) {
if ( $badtable =~ /Memory/i ) { if ( $badtable =~ /Memory/i ) {
badprint "Table $badtable is a MEMORY table. It's suggested to use only InnoDB tables in production"; badprint
} else { "Table $badtable is a MEMORY table. It's suggested to use only InnoDB tables in production";
}
else {
badprint "\t$badtable"; badprint "\t$badtable";
} }
$tmpContent .= "\n$badtable"; $tmpContent .= "\n$badtable";
} }
} else { }
else {
goodprint "All tables are InnoDB tables"; goodprint "All tables are InnoDB tables";
} }
dump_into_file( "tables_non_innodb.csv", $tmpContent ); dump_into_file( "tables_non_innodb.csv", $tmpContent );
@ -5823,7 +5873,8 @@ WHERE table_schema not in ('sys', 'mysql', 'performance_schema', 'information_sc
and (CHARacter_set_name NOT LIKE 'utf8%' and (CHARacter_set_name NOT LIKE 'utf8%'
or COLLATION_name NOT LIKE 'utf8%');" or COLLATION_name NOT LIKE 'utf8%');"
); );
$tmpContent='Schema,Table,Column, Charset, Collation, Data Type, Max Length'; $tmpContent =
'Schema,Table,Column, Charset, Collation, Data Type, Max Length';
if ( scalar(@nonutf8columns) > 0 ) { if ( scalar(@nonutf8columns) > 0 ) {
badprint "Following character columns(s) are not utf8 compliant:"; badprint "Following character columns(s) are not utf8 compliant:";
push @generalrec, push @generalrec,
@ -5845,7 +5896,8 @@ WHERE table_schema not in ('sys', 'mysql', 'performance_schema', 'information_sc
and (CHARacter_set_name LIKE 'utf8%' and (CHARacter_set_name LIKE 'utf8%'
or COLLATION_name LIKE 'utf8%');" or COLLATION_name LIKE 'utf8%');"
); );
$tmpContent='Schema,Table,Column, Charset, Collation, Data Type, Max Length'; $tmpContent =
'Schema,Table,Column, Charset, Collation, Data Type, Max Length';
foreach my $badtable (@utf8columns) { foreach my $badtable (@utf8columns) {
$tmpContent .= "\n$badtable"; $tmpContent .= "\n$badtable";
} }
@ -5864,6 +5916,7 @@ AND data_type='FULLTEXT';"
dump_into_file( "fulltext_columns.csv", $tmpContent ); dump_into_file( "fulltext_columns.csv", $tmpContent );
} }
# Recommendations for Galera # Recommendations for Galera
sub mariadb_galera { sub mariadb_galera {
subheaderprint "Galera Metrics"; subheaderprint "Galera Metrics";
@ -5902,7 +5955,6 @@ sub mariadb_galera {
infoprint "GCache is using " infoprint "GCache is using "
. hr_bytes_rnd( get_wsrep_option('gcache.mem_size') ); . hr_bytes_rnd( get_wsrep_option('gcache.mem_size') );
infoprint "CPU cores detected : " . (cpu_cores); infoprint "CPU cores detected : " . (cpu_cores);
infoprint "wsrep_slave_threads: " . get_wsrep_option('wsrep_slave_threads'); infoprint "wsrep_slave_threads: " . get_wsrep_option('wsrep_slave_threads');
@ -6198,7 +6250,8 @@ sub mysql_innodb {
if ( defined $myvar{'innodb_redo_log_capacity'} ) { if ( defined $myvar{'innodb_redo_log_capacity'} ) {
infoprint " +-- InnoDB Redo Log Capacity: " infoprint " +-- InnoDB Redo Log Capacity: "
. hr_bytes( $myvar{'innodb_redo_log_capacity'} ); . hr_bytes( $myvar{'innodb_redo_log_capacity'} );
} else { }
else {
if ( defined $myvar{'innodb_log_file_size'} ) { if ( defined $myvar{'innodb_log_file_size'} ) {
infoprint " +-- InnoDB Log File Size: " infoprint " +-- InnoDB Log File Size: "
. hr_bytes( $myvar{'innodb_log_file_size'} ); . hr_bytes( $myvar{'innodb_log_file_size'} );
@ -6212,10 +6265,10 @@ sub mysql_innodb {
. "(" . "("
. $mycalc{'innodb_log_size_pct'} . $mycalc{'innodb_log_size_pct'}
. " % of buffer pool)"; . " % of buffer pool)";
} else { }
else {
infoprint " +-- InnoDB Total Log File Size: " infoprint " +-- InnoDB Total Log File Size: "
. hr_bytes( $myvar{'innodb_log_file_size'} ) . hr_bytes( $myvar{'innodb_log_file_size'} ) . "("
. "("
. $mycalc{'innodb_log_size_pct'} . $mycalc{'innodb_log_size_pct'}
. " % of buffer pool)"; . " % of buffer pool)";
} }
@ -6242,32 +6295,54 @@ sub mysql_innodb {
# InnoDB Buffer Pool Size # InnoDB Buffer Pool Size
if ( $myvar{'innodb_file_per_table'} eq "ON" ) { if ( $myvar{'innodb_file_per_table'} eq "ON" ) {
goodprint "InnoDB File per table is activated"; goodprint "InnoDB File per table is activated";
} else { }
else {
badprint "InnoDB File per table is not activated"; badprint "InnoDB File per table is not activated";
push( @adjvars, "innodb_file_per_table=ON" ); push( @adjvars, "innodb_file_per_table=ON" );
} }
# InnoDB Buffer Pool Size # InnoDB Buffer Pool Size
if ( $arch == 32 && $myvar{'innodb_buffer_pool_size'} > 4294967295 ) { if ( $arch == 32 && $myvar{'innodb_buffer_pool_size'} > 4294967295 ) {
badprint "InnoDb Buffer Pool size limit reached for 32 bits architecture: (". hr_bytes(4294967295)." )"; badprint
push( @adjvars, "limit innodb_buffer_pool_size under ".hr_bytes(4294967295)." for 32 bits architecture"); "InnoDb Buffer Pool size limit reached for 32 bits architecture: ("
. hr_bytes(4294967295) . " )";
push( @adjvars,
"limit innodb_buffer_pool_size under "
. hr_bytes(4294967295)
. " for 32 bits architecture" );
} }
if ( $arch == 32 && $myvar{'innodb_buffer_pool_size'} < 4294967295 ) { if ( $arch == 32 && $myvar{'innodb_buffer_pool_size'} < 4294967295 ) {
goodprint "InnoDb Buffer Pool size ( " . hr_bytes($myvar{'innodb_buffer_pool_size'}). " ) under limit for 32 bits architecture: (". hr_bytes(4294967295 ).")"; goodprint "InnoDb Buffer Pool size ( "
. hr_bytes( $myvar{'innodb_buffer_pool_size'} )
. " ) under limit for 32 bits architecture: ("
. hr_bytes(4294967295) . ")";
} }
if ($arch == 64 && $myvar{'innodb_buffer_pool_size'} > 18446744073709551615 ) { if ( $arch == 64
badprint "InnoDb Buffer Pool size limit(". hr_bytes(18446744073709551615 ).") reached for 64 bits architecture"; && $myvar{'innodb_buffer_pool_size'} > 18446744073709551615 )
push( @adjvars, "limit innodb_buffer_pool_size under ".hr_bytes(18446744073709551615)." for 64 bits architecture"); {
badprint "InnoDb Buffer Pool size limit("
. hr_bytes(18446744073709551615)
. ") reached for 64 bits architecture";
push( @adjvars,
"limit innodb_buffer_pool_size under "
. hr_bytes(18446744073709551615)
. " for 64 bits architecture" );
} }
if ($arch == 64 && $myvar{'innodb_buffer_pool_size'} < 18446744073709551615 ) { if ( $arch == 64
goodprint "InnoDb Buffer Pool size ( " . hr_bytes($myvar{'innodb_buffer_pool_size'}). " ) under limit for 64 bits architecture: (". hr_bytes(18446744073709551615 )." )"; && $myvar{'innodb_buffer_pool_size'} < 18446744073709551615 )
{
goodprint "InnoDb Buffer Pool size ( "
. hr_bytes( $myvar{'innodb_buffer_pool_size'} )
. " ) under limit for 64 bits architecture: ("
. hr_bytes(18446744073709551615) . " )";
} }
if ( $myvar{'innodb_buffer_pool_size'} > $enginestats{'InnoDB'} ) { if ( $myvar{'innodb_buffer_pool_size'} > $enginestats{'InnoDB'} ) {
goodprint "InnoDB buffer pool / data size: " goodprint "InnoDB buffer pool / data size: "
. hr_bytes( $myvar{'innodb_buffer_pool_size'} ) . " / " . hr_bytes( $myvar{'innodb_buffer_pool_size'} ) . " / "
. hr_bytes( $enginestats{'InnoDB'} ) . ""; . hr_bytes( $enginestats{'InnoDB'} ) . "";
} else { }
else {
badprint "InnoDB buffer pool / data size: " badprint "InnoDB buffer pool / data size: "
. hr_bytes( $myvar{'innodb_buffer_pool_size'} ) . " / " . hr_bytes( $myvar{'innodb_buffer_pool_size'} ) . " / "
. hr_bytes( $enginestats{'InnoDB'} ) . ""; . hr_bytes( $enginestats{'InnoDB'} ) . "";
@ -6280,21 +6355,22 @@ sub mysql_innodb {
or $mycalc{'innodb_log_size_pct'} > 30 ) or $mycalc{'innodb_log_size_pct'} > 30 )
{ {
if ( defined $myvar{'innodb_redo_log_capacity'} ) { if ( defined $myvar{'innodb_redo_log_capacity'} ) {
badprint "Ratio InnoDB redo log capacity / InnoDB Buffer pool size (" badprint
"Ratio InnoDB redo log capacity / InnoDB Buffer pool size ("
. $mycalc{'innodb_log_size_pct'} . "%): " . $mycalc{'innodb_log_size_pct'} . "%): "
. hr_bytes( $myvar{'innodb_redo_log_capacity'} ) . " / " . hr_bytes( $myvar{'innodb_redo_log_capacity'} ) . " / "
. hr_bytes( $myvar{'innodb_buffer_pool_size'} ) . hr_bytes( $myvar{'innodb_buffer_pool_size'} )
. " should be equal to 25%"; . " should be equal to 25%";
push( push( @adjvars,
@adjvars,
"innodb_redo_log_capacity should be (=" "innodb_redo_log_capacity should be (="
. hr_bytes_rnd( . hr_bytes_rnd( $myvar{'innodb_buffer_pool_size'} / 4 )
$myvar{'innodb_buffer_pool_size'} / 4
)
. ") if possible, so InnoDB Redo log Capacity equals 25% of buffer pool size." . ") if possible, so InnoDB Redo log Capacity equals 25% of buffer pool size."
); );
push ( @generalrec, "Be careful, increasing innodb_redo_log_capacity means higher crash recovery mean time"); push( @generalrec,
} else { "Be careful, increasing innodb_redo_log_capacity means higher crash recovery mean time"
);
}
else {
badprint "Ratio InnoDB log file size / InnoDB Buffer pool size (" badprint "Ratio InnoDB log file size / InnoDB Buffer pool size ("
. $mycalc{'innodb_log_size_pct'} . "%): " . $mycalc{'innodb_log_size_pct'} . "%): "
. hr_bytes( $myvar{'innodb_log_file_size'} ) . " * " . hr_bytes( $myvar{'innodb_log_file_size'} ) . " * "
@ -6310,7 +6386,9 @@ sub mysql_innodb {
) )
. ") if possible, so InnoDB total log file size equals 25% of buffer pool size." . ") if possible, so InnoDB total log file size equals 25% of buffer pool size."
); );
push ( @generalrec, "Be careful, increasing innodb_log_file_size / innodb_log_files_in_group means higher crash recovery mean time"); push( @generalrec,
"Be careful, increasing innodb_log_file_size / innodb_log_files_in_group means higher crash recovery mean time"
);
} }
if ( mysql_version_le( 5, 6, 2 ) ) { if ( mysql_version_le( 5, 6, 2 ) ) {
push( @generalrec, push( @generalrec,
@ -6318,13 +6396,16 @@ sub mysql_innodb {
); );
} }
} else { }
else {
if ( defined $myvar{'innodb_redo_log_capacity'} ) { if ( defined $myvar{'innodb_redo_log_capacity'} ) {
goodprint "Ratio InnoDB Redo Log Capacity / InnoDB Buffer pool size: " goodprint
"Ratio InnoDB Redo Log Capacity / InnoDB Buffer pool size: "
. hr_bytes( $myvar{'innodb_redo_log_capacity'} ) . "/" . hr_bytes( $myvar{'innodb_redo_log_capacity'} ) . "/"
. hr_bytes( $myvar{'innodb_buffer_pool_size'} ) . hr_bytes( $myvar{'innodb_buffer_pool_size'} )
. " should be equal to 25%"; . " should be equal to 25%";
} else { }
else {
push( @generalrec, push( @generalrec,
"Before changing innodb_log_file_size and/or innodb_log_files_in_group read this: https://bit.ly/2TcGgtU" "Before changing innodb_log_file_size and/or innodb_log_files_in_group read this: https://bit.ly/2TcGgtU"
); );
@ -7274,7 +7355,7 @@ __END__
=head1 NAME =head1 NAME
MySQLTuner 2.2.5 - MySQL High Performance Tuning Script MySQLTuner 2.2.6 - MySQL High Performance Tuning Script
=head1 IMPORTANT USAGE GUIDELINES =head1 IMPORTANT USAGE GUIDELINES