Files
percona-toolkit/lib/VariableAdvisorRules.pm
Sveta Smirnova 8b802722db PT-2340 - Support MySQL 8.4
- Adjusted tools and tests which fail due to fixed update-modules command
- Adjsted t/pt-table-checksum/basics.t test for 8.0
2024-11-13 21:23:39 +03:00

646 lines
17 KiB
Perl

# This program is copyright 2010-2011 Percona Ireland Ltd.
# Feedback and improvements are welcome.
#
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# 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 the Free Software
# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar
# systems, you can issue `man perlgpl' or `man perlartistic' to read these
# licenses.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
# ###########################################################################
# VariableAdvisorRules package
# ###########################################################################
{
# Package: VariableAdvisorRules
# VariableAdvisorRules specifies rules for checking MySQL variables.
package VariableAdvisorRules;
use base 'AdvisorRules';
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
sub new {
my ( $class, %args ) = @_;
my $self = $class->SUPER::new(%args);
@{$self->{rules}} = $self->get_rules();
PTDEBUG && _d(scalar @{$self->{rules}}, "rules");
return $self;
}
# Each rules is a hashref with two keys:
# * id Unique PREFIX.NUMBER for the rule.
# * code Coderef to check rule, returns true if the rule matches.
sub get_rules {
return
{
id => 'auto_increment',
code => sub {
my ( %args ) = @_;
my $vars = $args{variables};
return unless defined $vars->{auto_increment_increment}
&& defined $vars->{auto_increment_offset};
return $vars->{auto_increment_increment} != 1
|| $vars->{auto_increment_offset} != 1 ? 1 : 0;
},
},
{
id => 'concurrent_insert',
code => sub {
my ( %args ) = @_;
# MySQL 5.5 has named values.
# http://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html
# https://bugs.launchpad.net/percona-toolkit/+bug/898138
if ( $args{variables}->{concurrent_insert}
&& $args{variables}->{concurrent_insert} =~ m/[^\d]/ ) {
return $args{variables}->{concurrent_insert} eq 'ALWAYS' ? 1 : 0;
}
return _var_gt($args{variables}->{concurrent_insert}, 1);
},
},
{
id => 'connect_timeout',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{connect_timeout}, 10);
},
},
{
id => 'debug',
code => sub {
my ( %args ) = @_;
return $args{variables}->{debug} ? 1 : 0;
},
},
{
id => 'delay_key_write',
code => sub {
my ( %args ) = @_;
return _var_seq($args{variables}->{delay_key_write}, "ON");
},
},
{
id => 'flush',
code => sub {
my ( %args ) = @_;
return _var_seq($args{variables}->{flush}, "ON");
},
},
{
id => 'flush_time',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{flush_time}, 0);
},
},
{
id => 'have_bdb',
code => sub {
my ( %args ) = @_;
return _var_seq($args{variables}->{have_bdb}, 'YES');
},
},
{
id => 'init_connect',
code => sub {
my ( %args ) = @_;
return $args{variables}->{init_connect} ? 1 : 0;
},
},
{
id => 'init_file',
code => sub {
my ( %args ) = @_;
return $args{variables}->{init_file} ? 1 : 0;
},
},
{
id => 'init_slave',
code => sub {
my ( %args ) = @_;
return $args{variables}->{init_slave} ? 1 : 0;
},
},
{
id => 'init_replica',
code => sub {
my ( %args ) = @_;
return $args{variables}->{init_replica} ? 1 : 0;
},
},
{
id => 'innodb_additional_mem_pool_size',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{innodb_additional_mem_pool_size},
20 * 1_048_576); # 20M
},
},
{
id => 'innodb_buffer_pool_size',
code => sub {
my ( %args ) = @_;
return _var_eq($args{variables}->{innodb_buffer_pool_size},
128 * 1_048_576); # 128M
},
},
{
id => 'innodb_checksums',
code => sub {
my ( %args ) = @_;
return _var_sneq($args{variables}->{innodb_checksums}, "ON");
},
},
{
id => 'innodb_doublewrite',
code => sub {
my ( %args ) = @_;
return _var_sneq($args{variables}->{innodb_doublewrite}, "ON");
},
},
{
id => 'innodb_fast_shutdown',
code => sub {
my ( %args ) = @_;
return _var_neq($args{variables}->{innodb_fast_shutdown}, 1);
},
},
{
id => 'innodb_flush_log_at_trx_commit-1',
code => sub {
my ( %args ) = @_;
return _var_neq($args{variables}->{innodb_flush_log_at_trx_commit}, 1);
},
},
{
id => 'innodb_flush_log_at_trx_commit-2',
code => sub {
my ( %args ) = @_;
return _var_eq($args{variables}->{innodb_flush_log_at_trx_commit}, 0);
},
},
{
id => 'innodb_force_recovery',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{innodb_force_recovery}, 0);
},
},
{
id => 'innodb_lock_wait_timeout',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{innodb_lock_wait_timeout}, 50);
},
},
{
id => 'innodb_log_buffer_size',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{innodb_log_buffer_size},
64 * 1_048_576); # 64M
},
},
{
id => 'innodb_log_file_size',
code => sub {
my ( %args ) = @_;
return _var_eq($args{variables}->{innodb_log_file_size},
48 * 1_048_576); # 48M
},
},
{
id => 'innodb_max_dirty_pages_pct',
code => sub {
my ( %args ) = @_;
my $mysql_version = $args{mysql_version};
return 0 unless $mysql_version;
return _var_lt($args{variables}->{innodb_max_dirty_pages_pct},
($mysql_version < '5.5' ? 90 : 75));
},
},
{
id => 'key_buffer_size',
code => sub {
my ( %args ) = @_;
return _var_eq($args{variables}->{key_buffer_size},
8 * 1_048_576); # 8M
},
},
{
id => 'large_pages',
code => sub {
my ( %args ) = @_;
return _var_seq($args{variables}->{large_pages}, "ON");
},
},
{
id => 'locked_in_memory',
code => sub {
my ( %args ) = @_;
return _var_seq($args{variables}->{locked_in_memory}, "ON");
},
},
{
id => 'log_warnings-1',
code => sub {
my ( %args ) = @_;
return _var_eq($args{variables}->{log_warnings}, 0);
},
},
{
id => 'log_warnings-2',
code => sub {
my ( %args ) = @_;
return _var_eq($args{variables}->{log_warnings}, 1);
},
},
{
id => 'low_priority_updates',
code => sub {
my ( %args ) = @_;
return _var_seq($args{variables}->{low_priority_updates}, "ON");
},
},
{
id => 'max_binlog_size',
code => sub {
my ( %args ) = @_;
return _var_lt($args{variables}->{max_binlog_size},
1 * 1_073_741_824); # 1G
},
},
{
id => 'max_connect_errors',
code => sub {
my ( %args ) = @_;
return _var_eq($args{variables}->{max_connect_errors}, 10);
},
},
{
id => 'max_connections',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{max_connections}, 1_000);
},
},
{
id => 'myisam_repair_threads',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{myisam_repair_threads}, 1);
},
},
{
id => 'old_passwords',
code => sub {
my ( %args ) = @_;
return _var_seq($args{variables}->{old_passwords}, "ON");
},
},
{
id => 'optimizer_prune_level',
code => sub {
my ( %args ) = @_;
return _var_lt($args{variables}->{optimizer_prune_level}, 1);
},
},
{
id => 'port',
code => sub {
my ( %args ) = @_;
return _var_neq($args{variables}->{port}, 3306);
},
},
{
id => 'query_cache_size-1',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{query_cache_size},
128 * 1_048_576); # 128M
},
},
{
id => 'query_cache_size-2',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{query_cache_size},
512 * 1_048_576); # 512M
},
},
{
id => 'query_cache_size-3',
code => sub {
my ( %args ) = @_;
return _var_neq($args{variables}->{query_cache_size}, 0);
},
},
{
id => 'read_buffer_size-1',
code => sub {
my ( %args ) = @_;
return _var_neq($args{variables}->{read_buffer_size}, 131_072);
},
},
{
id => 'read_buffer_size-2',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{read_buffer_size},
8 * 1_048_576); # 8M
},
},
{
id => 'read_rnd_buffer_size-1',
code => sub {
my ( %args ) = @_;
return _var_neq($args{variables}->{read_rnd_buffer_size}, 262_144);
},
},
{
id => 'read_rnd_buffer_size-2',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{read_rnd_buffer_size},
4 * 1_048_576); # 4M
},
},
{
id => 'relay_log_space_limit',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{relay_log_space_limit}, 0);
},
},
{
id => 'slave_net_timeout',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{slave_net_timeout}, 60);
},
},
{
id => 'replica_net_timeout',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{replica_net_timeout}, 60);
},
},
{
id => 'slave_skip_errors',
code => sub {
my ( %args ) = @_;
return $args{variables}->{slave_skip_errors}
&& $args{variables}->{slave_skip_errors} ne 'OFF' ? 1 : 0;
},
},
{
id => 'replica_skip_errors',
code => sub {
my ( %args ) = @_;
return $args{variables}->{replica_skip_errors}
&& $args{variables}->{replica_skip_errors} ne 'OFF' ? 1 : 0;
},
},
{
id => 'sort_buffer_size-1',
code => sub {
my ( %args ) = @_;
return _var_neq($args{variables}->{sort_buffer_size}, 2_097_144);
},
},
{
id => 'sort_buffer_size-2',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{sort_buffer_size},
4 * 1_048_576); # 4M
},
},
{
id => 'sql_notes',
code => sub {
my ( %args ) = @_;
return _var_seq($args{variables}->{sql_notes}, "OFF");
},
},
{
id => 'sync_frm',
code => sub {
my ( %args ) = @_;
return _var_sneq($args{variables}->{sync_frm}, "ON");
},
},
{
id => 'tx_isolation-1',
code => sub {
my ( %args ) = @_;
return _var_sneq($args{variables}->{tx_isolation}, "REPEATABLE-READ");
},
},
{
id => 'tx_isolation-2',
code => sub {
my ( %args ) = @_;
return
_var_sneq($args{variables}->{tx_isolation}, "REPEATABLE-READ")
&& _var_sneq($args{variables}->{tx_isolation}, "READ-COMMITTED")
? 1 : 0;
},
},
{
id => 'expire_logs_days',
code => sub {
my ( %args ) = @_;
return _var_eq($args{variables}->{expire_logs_days}, 0)
&& _var_seq($args{variables}->{log_bin}, "ON");
},
},
{
id => 'innodb_file_io_threads',
code => sub {
my ( %args ) = @_;
return _var_neq($args{variables}->{innodb_file_io_threads}, 4)
&& $OSNAME ne 'MSWin32' ? 1 : 0;
},
},
{
id => 'innodb_data_file_path',
code => sub {
my ( %args ) = @_;
return
($args{variables}->{innodb_data_file_path} || '') =~ m/autoextend/
? 1 : 0;
},
},
{
id => 'innodb_flush_method',
code => sub {
my ( %args ) = @_;
return _var_sneq($args{variables}->{innodb_flush_method}, 'O_DIRECT')
&& $OSNAME ne 'MSWin32' ? 1 : 0;
},
},
{
id => 'innodb_locks_unsafe_for_binlog',
code => sub {
my ( %args ) = @_;
return _var_seq($args{variables}->{innodb_locks_unsafe_for_binlog},
"ON") && _var_seq($args{variables}->{log_bin}, "ON");
},
},
{
id => 'innodb_support_xa',
code => sub {
my ( %args ) = @_;
return _var_sneq($args{variables}->{innodb_support_xa}, "ON")
&& _var_seq($args{variables}->{log_bin}, "ON");
},
},
{
id => 'log_bin',
code => sub {
my ( %args ) = @_;
return _var_sneq($args{variables}->{log_bin}, "ON");
},
},
{
id => 'log_output',
code => sub {
my ( %args ) = @_;
return ($args{variables}->{log_output} || '') =~ m/TABLE/i ? 1 : 0;
},
},
{
id => 'max_relay_log_size',
code => sub {
my ( %args ) = @_;
return _var_gt($args{variables}->{max_relay_log_size}, 0)
&& _var_lt($args{variables}->{max_relay_log_size},
1 * 1_073_741_824) ? 1 : 0;
},
},
{
id => 'myisam_recover_options',
code => sub {
my ( %args ) = @_;
return _var_seq($args{variables}->{myisam_recover_options}, "OFF")
|| _var_seq($args{variables}->{myisam_recover_options}, "DEFAULT")
? 1 : 0;
},
},
{
id => 'storage_engine',
code => sub {
my ( %args ) = @_;
return 0 unless $args{variables}->{storage_engine};
return $args{variables}->{storage_engine} !~ m/InnoDB/i ? 1 : 0;
},
},
{
id => 'sync_binlog',
code => sub {
my ( %args ) = @_;
return
_var_seq($args{variables}->{log_bin}, "ON")
&& ( _var_eq($args{variables}->{sync_binlog}, 0)
|| _var_gt($args{variables}->{sync_binlog}, 1)) ? 1 : 0;
},
},
{
id => 'tmp_table_size',
code => sub {
my ( %args ) = @_;
return ($args{variables}->{tmp_table_size} || 0)
> ($args{variables}->{max_heap_table_size} || 0) ? 1 : 0;
},
},
{
id => 'old mysql version',
code => sub {
my ( %args ) = @_;
my $mysql_version = $args{mysql_version};
return 0 unless $mysql_version;
return 1 if ($mysql_version == '3' && $mysql_version < '3.23' )
|| ($mysql_version == '4' && $mysql_version < '4.1.20')
|| ($mysql_version == '5.0' && $mysql_version < '5.0.37')
|| ($mysql_version == '5.1' && $mysql_version < '5.1.30')
|| ($mysql_version == '5.5' && $mysql_version < '5.5.8')
|| ($mysql_version == '5.6' && $mysql_version < '5.6.10')
|| ($mysql_version == '5.7' && $mysql_version < '5.7.9')
|| ($mysql_version == '8.0' && $mysql_version < '8.0.11')
;
return 0;
},
},
{
id => 'end-of-life mysql version',
code => sub {
my ( %args ) = @_;
my $mysql_version = $args{mysql_version};
return 0 unless $mysql_version;
return $mysql_version < '8.0' ? 1 : 0; # 8.x
},
},
};
sub _var_gt {
my ($var, $val) = @_;
return 0 unless defined $var;
return $var > $val ? 1 : 0;
}
sub _var_lt {
my ($var, $val) = @_;
return 0 unless defined $var;
return $var < $val ? 1 : 0;
}
sub _var_eq {
my ($var, $val) = @_;
return 0 unless defined $var;
return $var == $val ? 1 : 0;
}
sub _var_neq {
my ($var, $val) = @_;
return 0 unless defined $var;
return _var_eq($var, $val) ? 0 : 1;
}
sub _var_seq {
my ($var, $val) = @_;
return 0 unless defined $var;
return $var eq $val ? 1 : 0;
}
sub _var_sneq {
my ($var, $val) = @_;
return 0 unless defined $var;
return _var_seq($var, $val) ? 0 : 1;
}
sub _d {
my ($package, undef, $line) = caller 0;
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
map { defined $_ ? $_ : 'undef' }
@_;
print STDERR "# $package:$line $PID ", join(' ', @_), "\n";
}
1;
}
# ###########################################################################
# End VariableAdvisorRules package
# ###########################################################################