@@ -1970,6 +1970,7 @@ sub execute_system_command {
19701970}
19711971
19721972sub mysql_setup {
1973+ $mysqllogin = ' ' ;
19731974 $doremote = 0;
19741975 $remotestring = ' ' ;
19751976 my $transport_prefix = get_transport_prefix();
@@ -5105,20 +5106,36 @@ sub calculations {
51055106 . $mycalc {' pct_max_physical_memory' } . " %" ;
51065107
51075108 # Slow queries
5108- $mycalc {' pct_slow_queries' } =
5109- int ( ( $mystat {' Slow_queries' } / $mystat {' Questions' } ) * 100 );
5109+ if ( $mystat {' Questions' } > 0 ) {
5110+ $mycalc {' pct_slow_queries' } =
5111+ int ( ( $mystat {' Slow_queries' } / $mystat {' Questions' } ) * 100 );
5112+ }
5113+ else {
5114+ $mycalc {' pct_slow_queries' } = 0;
5115+ }
51105116
51115117 # Connections
5112- $mycalc {' pct_connections_used' } = int (
5113- ( $mystat {' Max_used_connections' } / $myvar {' max_connections' } ) * 100 );
5118+ if ( $myvar {' max_connections' } > 0 ) {
5119+ $mycalc {' pct_connections_used' } = int (
5120+ ( $mystat {' Max_used_connections' } / $myvar {' max_connections' } ) *
5121+ 100 );
5122+ }
5123+ else {
5124+ $mycalc {' pct_connections_used' } = 0;
5125+ }
51145126 $mycalc {' pct_connections_used' } =
51155127 ( $mycalc {' pct_connections_used' } > 100 )
51165128 ? 100
51175129 : $mycalc {' pct_connections_used' };
51185130
51195131 # Aborted Connections
5120- $mycalc {' pct_connections_aborted' } =
5121- percentage( $mystat {' Aborted_connects' }, $mystat {' Connections' } );
5132+ if ( $mystat {' Connections' } > 0 ) {
5133+ $mycalc {' pct_connections_aborted' } =
5134+ percentage( $mystat {' Aborted_connects' }, $mystat {' Connections' } );
5135+ }
5136+ else {
5137+ $mycalc {' pct_connections_aborted' } = 0;
5138+ }
51225139 debugprint " Aborted_connects: " . $mystat {' Aborted_connects' } . " " ;
51235140 debugprint " Connections: " . $mystat {' Connections' } . " " ;
51245141 debugprint " pct_connections_aborted: "
@@ -5239,13 +5256,20 @@ sub calculations {
52395256 $mycalc {' query_cache_efficiency' } = 0;
52405257 }
52415258 elsif ( mysql_version_ge(4) ) {
5242- $mycalc {' query_cache_efficiency' } = sprintf (
5243- " %.1f" ,
5244- (
5245- $mystat {' Qcache_hits' } /
5246- ( $mystat {' Com_select' } + $mystat {' Qcache_hits' } )
5247- ) * 100
5248- );
5259+ if ( ( $mystat {' Com_select' } || 0 ) + ( $mystat {' Qcache_hits' } || 0 ) >
5260+ 0 )
5261+ {
5262+ $mycalc {' query_cache_efficiency' } = sprintf (
5263+ " %.1f" ,
5264+ (
5265+ $mystat {' Qcache_hits' } /
5266+ ( $mystat {' Com_select' } + $mystat {' Qcache_hits' } )
5267+ ) * 100
5268+ );
5269+ }
5270+ else {
5271+ $mycalc {' query_cache_efficiency' } = 0;
5272+ }
52495273 if ( $myvar {' query_cache_size' } ) {
52505274 $mycalc {' pct_query_cache_used' } = sprintf (
52515275 " %.1f" ,
@@ -5254,28 +5278,40 @@ sub calculations {
52545278 ) * 100
52555279 );
52565280 }
5257- if ( $mystat {' Qcache_lowmem_prunes' } == 0 ) {
5281+ if ( ( $mystat {' Qcache_lowmem_prunes' } || 0 ) == 0 ) {
52585282 $mycalc {' query_cache_prunes_per_day' } = 0;
52595283 }
52605284 else {
5261- $mycalc {' query_cache_prunes_per_day' } = int (
5262- $mystat {' Qcache_lowmem_prunes' } / ( $mystat {' Uptime' } / 86400 )
5263- );
5285+ if ( ( $mystat {' Uptime' } || 0 ) > 0 ) {
5286+ $mycalc {' query_cache_prunes_per_day' } = int (
5287+ $mystat {' Qcache_lowmem_prunes' } /
5288+ ( $mystat {' Uptime' } / 86400 ) );
5289+ }
5290+ else {
5291+ $mycalc {' query_cache_prunes_per_day' } = 0;
5292+ }
52645293 }
52655294 }
52665295
52675296 # Sorting
5268- $mycalc {' total_sorts' } = $mystat {' Sort_scan' } + $mystat {' Sort_range' };
5297+ $mycalc {' total_sorts' } =
5298+ ( $mystat {' Sort_scan' } || 0 ) + ( $mystat {' Sort_range' } || 0 );
52695299 if ( $mycalc {' total_sorts' } > 0 ) {
52705300 $mycalc {' pct_temp_sort_table' } = int (
52715301 ( $mystat {' Sort_merge_passes' } / $mycalc {' total_sorts' } ) * 100 );
52725302 }
52735303
52745304 # Joins
52755305 $mycalc {' joins_without_indexes' } =
5276- $mystat {' Select_range_check' } + $mystat {' Select_full_join' };
5277- $mycalc {' joins_without_indexes_per_day' } =
5278- int ( $mycalc {' joins_without_indexes' } / ( $mystat {' Uptime' } / 86400 ) );
5306+ ( $mystat {' Select_range_check' } || 0 ) +
5307+ ( $mystat {' Select_full_join' } || 0 );
5308+ if ( ( $mystat {' Uptime' } || 0 ) > 0 ) {
5309+ $mycalc {' joins_without_indexes_per_day' } = int (
5310+ $mycalc {' joins_without_indexes' } / ( $mystat {' Uptime' } / 86400 ) );
5311+ }
5312+ else {
5313+ $mycalc {' joins_without_indexes_per_day' } = 0;
5314+ }
52795315
52805316 # Temporary tables
52815317 if ( $mystat {' Created_tmp_tables' } > 0 ) {
@@ -5333,9 +5369,15 @@ sub calculations {
53335369 }
53345370
53355371 # Thread cache
5336- $mycalc {' thread_cache_hit_rate' } =
5337- int ( 100 -
5338- ( ( $mystat {' Threads_created' } / $mystat {' Connections' } ) * 100 ) );
5372+ if ( ( $mystat {' Connections' } || 0 ) > 0 ) {
5373+ $mycalc {' thread_cache_hit_rate' } =
5374+ int ( 100 -
5375+ ( ( $mystat {' Threads_created' } / $mystat {' Connections' } ) * 100 )
5376+ );
5377+ }
5378+ else {
5379+ $mycalc {' thread_cache_hit_rate' } = 100;
5380+ }
53395381
53405382 # Other
53415383 if ( $mystat {' Connections' } > 0 ) {
@@ -5945,6 +5987,41 @@ sub mysql_stats {
59455987
59465988 push ( @adjvars ,
59475989 $table_cache_var . " (> " . $myvar {$table_cache_var } . " )" );
5990+
5991+ # table_open_cache_instances recommendation (#480)
5992+ if ( mysql_version_ge( 5, 6, 6 )
5993+ and $myvar {' version' } !~ / mariadb/i
5994+ and defined $myvar {' table_open_cache_instances' } )
5995+ {
5996+ my $logical_cpus = logical_cpu_cores();
5997+ if ( $logical_cpus > 1 ) {
5998+ my $recommended_instances =
5999+ POSIX::ceil( $logical_cpus * 0.5 );
6000+
6001+ # Cap at 16 (default for 8.0+)
6002+ $recommended_instances = 16 if $recommended_instances > 16;
6003+ if ( $myvar {' table_open_cache_instances' } <
6004+ $recommended_instances )
6005+ {
6006+ badprint
6007+ " table_open_cache_instances is set to $myvar {'table_open_cache_instances'} but $recommended_instances is recommended based on CPU cores." ;
6008+ push ( @adjvars ,
6009+ " table_open_cache_instances (=$recommended_instances )"
6010+ );
6011+ }
6012+ }
6013+ }
6014+ elsif ( $myvar {' version' } =~ / mariadb/i
6015+ and mysql_version_ge( 10, 2, 2 ) )
6016+ {
6017+ if ( defined $myvar {' table_open_cache_instances' }
6018+ and $myvar {' table_open_cache_instances' } > 0 )
6019+ {
6020+ infoprint
6021+ " MariaDB 10.2.2+ autosizes table_open_cache_instances. Current value is $myvar {'table_open_cache_instances'}." ;
6022+ }
6023+ }
6024+
59486025 push ( @generalrec ,
59496026 " Increase "
59506027 . $table_cache_var
@@ -9091,98 +9168,72 @@ sub mysql_innodb {
90919168# InnoDB Log File Size / InnoDB Redo Log Capacity Recommendations
90929169# For MySQL < 8.0.30, the recommendation is based on innodb_log_file_size and innodb_log_files_in_group.
90939170# For MySQL >= 8.0.30, innodb_redo_log_capacity replaces the old system.
9094- if ( mysql_version_ge( 8, 0, 30 )
9095- && defined $myvar {' innodb_redo_log_capacity' } )
9096- {
9097- # Recalculate ratio if needed (ensure accuracy for modern systems)
9098- if ( defined $myvar {' innodb_buffer_pool_size' }
9099- && $myvar {' innodb_buffer_pool_size' } > 0 )
9100- {
9101- $mycalc {' innodb_log_size_pct' } =
9102- ( $myvar {' innodb_redo_log_capacity' } /
9103- $myvar {' innodb_buffer_pool_size' } ) * 100;
9104- }
9105-
9106- infoprint " InnoDB Redo Log Capacity is set to "
9107- . hr_bytes( $myvar {' innodb_redo_log_capacity' } );
9171+ if ( mysql_version_ge( 8, 0, 30 ) ) {
9172+ if ( defined $myvar {' innodb_redo_log_capacity' } ) {
9173+ infoprint " InnoDB Redo Log Capacity is set to "
9174+ . hr_bytes( $myvar {' innodb_redo_log_capacity' } );
91089175
9109- if ( defined $myvar {' innodb_dedicated_server' }
9110- and $myvar {' innodb_dedicated_server' } eq ' ON' )
9111- {
9112- goodprint
9176+ if ( defined $myvar {' innodb_dedicated_server' }
9177+ and $myvar {' innodb_dedicated_server' } eq ' ON' )
9178+ {
9179+ goodprint
91139180" innodb_dedicated_server is ON. MySQL is managing Redo Log Capacity automatically." ;
9114- }
9115- else {
9116- my $innodb_os_log_written = $mystat {' Innodb_os_log_written' } || 0;
9117- my $uptime = $mystat {' Uptime' } || 1;
9181+ if ( defined $opt {' defaults-file' } || defined $opt {' defaults-extra-file' } ) {
9182+ infoprint " If innodb_redo_log_capacity is manually set in config, consider removing it." ;
9183+ }
9184+ }
9185+ else {
9186+ my $innodb_os_log_written = $mystat {' Innodb_os_log_written' } || 0;
9187+ my $uptime = $mystat {' Uptime' } || 1;
91189188
9119- if ( $uptime > 3600 ) {
9120- my $hourly_rate = $innodb_os_log_written / ( $uptime / 3600 );
9121- infoprint " Hourly InnoDB log write rate: "
9122- . hr_bytes($hourly_rate ) . " /hour" ;
9189+ if ( $uptime > 3600 ) {
9190+ my $hourly_rate = $innodb_os_log_written / ( $uptime / 3600 );
9191+ infoprint " Hourly InnoDB log write rate: "
9192+ . hr_bytes($hourly_rate ) . " /hour" ;
91239193
9124- # Determine recommendation based on RAM and workload
9125- my $recommended_bytes = $hourly_rate ;
9126- my $recommended_str = " " ;
9194+ # Determine recommendation based on workload
9195+ my $recommended_bytes = $hourly_rate ;
91279196
9128- if ( $physical_memory < 2 * 1024 * 1024 * 1024 ) {
9197+ # Sensible minimum based on RAM
9198+ my $min_bytes = 100 * 1024 * 1024;
9199+ if ( $physical_memory > 8 * 1024 * 1024 * 1024 ) {
9200+ $min_bytes = 1 * 1024 * 1024 * 1024;
9201+ }
9202+ $recommended_bytes = $min_bytes if $recommended_bytes < $min_bytes ;
91299203
9130- # < 2GB RAM: Default to 100MB if workload is low
9131- $recommended_bytes = 100 * 1024 * 1024
9132- if $recommended_bytes < 100 * 1024 * 1024 ;
9204+ # Cap at 16GB
9205+ my $max_bytes = 16 * 1024 * 1024 * 1024;
9206+ $recommended_bytes = $max_bytes if $recommended_bytes > $max_bytes ;
91339207
9134- # Round to 100MB
9135- $recommended_bytes =
9136- POSIX::ceil( $recommended_bytes / ( 100 * 1024 * 1024 ) )
9137- * ( 100 * 1024 * 1024 );
9138- $recommended_str = hr_bytes($recommended_bytes );
9139- }
9140- elsif ( $physical_memory < 8 * 1024 * 1024 * 1024 ) {
9141-
9142- # < 8GB RAM: Round to 100MB, max 1GB
9143- $recommended_bytes = 100 * 1024 * 1024
9144- if $recommended_bytes < 100 * 1024 * 1024;
9145- $recommended_bytes =
9146- POSIX::ceil( $recommended_bytes / ( 100 * 1024 * 1024 ) )
9147- * ( 100 * 1024 * 1024 );
9148- $recommended_bytes = 1 * 1024 * 1024 * 1024
9149- if $recommended_bytes > 1 * 1024 * 1024 * 1024;
9150- $recommended_str = hr_bytes($recommended_bytes );
9151- }
9152- else {
9153- # >= 8GB RAM: Round to 1GB, max 16GB
9154- $recommended_bytes = 1 * 1024 * 1024 * 1024
9155- if $recommended_bytes < 1 * 1024 * 1024 * 1024;
9156- $recommended_bytes =
9157- POSIX::ceil( $recommended_bytes / ( 1024 * 1024 * 1024 ) )
9158- * ( 1024 * 1024 * 1024 );
9159- $recommended_bytes = 16 * 1024 * 1024 * 1024
9160- if $recommended_bytes > 16 * 1024 * 1024 * 1024;
9161- $recommended_str = hr_bytes($recommended_bytes );
9162- }
9208+ # Rounding
9209+ if ( $recommended_bytes < 1024 * 1024 * 1024 ) {
9210+ $recommended_bytes =
9211+ POSIX::ceil( $recommended_bytes / ( 100 * 1024 * 1024 ) )
9212+ * ( 100 * 1024 * 1024 );
9213+ }
9214+ else {
9215+ $recommended_bytes =
9216+ POSIX::ceil( $recommended_bytes / ( 1024 * 1024 * 1024 ) )
9217+ * ( 1024 * 1024 * 1024 );
9218+ }
91639219
9164- if ( $myvar {' innodb_redo_log_capacity' } <
9165- $recommended_bytes * 0.9 )
9166- { # 10% tolerance
9167- badprint
9168- " Your innodb_redo_log_capacity is smaller than the recommended $recommended_str based on your workload and RAM." ;
9169- push ( @adjvars ,
9170- " innodb_redo_log_capacity (>= $recommended_str )" );
9220+ my $recommended_str = hr_bytes($recommended_bytes );
9221+ if ( $myvar {' innodb_redo_log_capacity' } < $recommended_bytes * 0.9 ) {
9222+ badprint " Your innodb_redo_log_capacity is smaller than the recommended $recommended_str based on your workload." ;
9223+ push @adjvars , " innodb_redo_log_capacity (>= $recommended_str )" ;
9224+ }
9225+ else {
9226+ goodprint " Your innodb_redo_log_capacity is sized correctly for your workload ($recommended_str recommended)." ;
9227+ }
91719228 }
91729229 else {
9173- goodprint
9174- " Your innodb_redo_log_capacity is sized correctly for your workload ($recommended_str recommended)." ;
9230+ infoprint " Server uptime is less than 1 hour. Cannot make a reliable recommendation for innodb_redo_log_capacity." ;
91759231 }
91769232 }
9177- else {
9178- infoprint
9179- " Server uptime is less than 1 hour. Cannot make a reliable recommendation for innodb_redo_log_capacity." ;
9180- }
91819233 }
91829234 }
9183- elsif ( !mysql_version_ge( 8, 0, 30 ) ) {
9184-
9185- # Keep existing logic for older versions
9235+ else {
9236+ # MySQL < 8.0.30: logic based on 25% ratio of buffer pool
91869237 if ( $mycalc {' innodb_log_size_pct' } < 20
91879238 or $mycalc {' innodb_log_size_pct' } > 30 )
91889239 {
0 commit comments