RQG: SlaveCrashRecovery Reporter

Май 8th, 2013 | Posted by elenst in MariaDB | Pensieve | Testing - (Комментарии отключены)

The reporter can be used to test crash-safety of replication.

It is a periodic reporter, every 30 seconds it kills the slave server using SIGKILL, and immediately restarts it on the old data directory, with the same parameters as before. On server restart, the reporter checks that the server itself and the replication started all right.

The reporter itself does not check consistency of the data, but it can be used together with ReplicationConsistency reporter.

It is supposed to be used with runall-new.pl, so that the server is started without MTR involvement.

Some more information at https://kb.askmonty.org/en/rqg-extensions-for-mariadb-features/

RQG: LimitRowsExamined Transformer

Май 8th, 2013 | Posted by elenst in MariaDB | Pensieve | Testing - (Комментарии отключены)

There are many things in RQG for which it’s not obvious what they do by a quick look. It becomes especially embarrassing though when those are things that you developed yourself; so, I’ll try to keep track of those at least, and maybe add some records for legacy components when I can.

The LimitRowsExamined transformer checks whether the original query already contains a ROWS EXAMINED clause. If it does not, it adds the clause either after the LIMIT clause, or at the end of the query. In any case (even if ROWS EXAMINED was already there), the transformer returns the following sequence of statements:

* FLUSH STATUS
* the query with ROWS EXAMINED
* a query which sums up status variables related to examined rows

The result of the main query is checked to be a subset of the original query’s result set. The sum of status variables is checked to be not greater than the limit provided in the ROWS EXAMINED clause, plus a margin. The margin is configured in the transformer.

Some more information at https://kb.askmonty.org/en/rqg-extensions-for-mariadb-features/

RQG: grammar keywords

Декабрь 11th, 2012 | Posted by elenst in Pensieve | Testing - (Комментарии отключены)

Since I’m totally lost in the github version of the RQG documentation, and can only find things there by pure chance, I will start adding here links to useful parts and pages I ran into; and if I don’t find something and have to figure it out by myself, I will put it here too. Maybe later, if it has enough contents, we will move it to AskMonty KnowledgeBase, but so far let it be here.

There used to be a nice list of keywords (e.g. _table, _field etc.) that can be used in a grammar file, but I can’t find it anymore. So, lets see what FromGrammar.pm accepts and returns.

letter || _letter :
$_ = $prng->letter();

digit || _digit :
$_ = $prng->digit();

_table :
$tables = $executors->[0]->metaTables($last_database);
$last_table = $prng->arrayElement($tables);
$_ = '`'.$last_table.'`';

_field :
$fields = $executors->[0]->metaColumns($last_table, $last_database);
$_ = '`'.$prng->arrayElement($fields).'`';

_hex :
$_ = $prng->hex();

_cwd :
$_ = "'".$cwd."'";

_tmpnam || tmpnam || _tmpfile :
# Create a new temporary file name and record it for unlinking at the next statement
$generator->[GENERATOR_TMPNAM] = tmpdir()."gentest".abs($$).".tmp" if not defined $generator->[GENERATOR_TMPNAM];
$_ = "'".$generator->[GENERATOR_TMPNAM]."'";
$_ =~ s{\\}{\\\\}sgio if osWindows();   # Backslash-escape backslashes on Windows

_tmptable :
$_ = "tmptable".abs($$);

_unix_timestamp :
$_ = time();

_pid :
$_ = abs($$);

_thread_id :
$_ = $generator->threadId();

_thread_count :
$_ = $ENV{RQG_THREADS};

_database || _db || _schema :
my $databases = $executors->[0]->metaSchemas();
$last_database = $prng->arrayElement($databases);
$_ = '`'.$last_database.'`';

_field_list :
my $fields = $executors->[0]->metaColumns($last_table, $last_database);
$_ = '`'.join('`,`', @$fields).'`';

_field_count :
my $fields = $executors->[0]->metaColumns($last_table, $last_database);
$_ = $#$fields + 1;

_field_next :
# Pick the next field that has not been picked recently and increment the $field_pos counter
my $fields = $executors->[0]->metaColumns($last_table, $last_database);
$_ = '`'.$fields->[$field_pos++ % $#$fields].'`';

_field_no_pk :
my $fields = $executors->[0]->metaColumnsTypeNot('primary',$last_table, $last_database);
$_ = '`'.$prng->arrayElement($fields).'`';

_field_indexed || _field_key :
my $fields_indexed = $executors->[0]->metaColumnsType('indexed',$last_table, $last_database);
$_ = '`'.$prng->arrayElement($fields_indexed).'`';

_field_unindexed || _field_nokey :
my $fields_unindexed = $executors->[0]->metaColumnsTypeNot('indexed',$last_table, $last_database);
$_ = '`'.$prng->arrayElement($fields_unindexed).'`';

_collation :
my $collations = $executors->[0]->metaCollations();
$_ = '_'.$prng->arrayElement($collations);

_collation_name :
my $collations = $executors->[0]->metaCollations();
$_ = $prng->arrayElement($collations);

_charset :
my $charsets = $executors->[0]->metaCharactersets();
$_ = '_'.$prng->arrayElement($charsets);

_charset_name :
my $charsets = $executors->[0]->metaCharactersets();
$_ = $prng->arrayElement($charsets);

_data :
$_ = $prng->file($cwd."/data");

# Additional logic, another time...

} elsif (
($field_type == FIELD_TYPE_NUMERIC) ||
($field_type == FIELD_TYPE_BLOB)
) {
$_ = $prng->fieldType($_);
} elsif ($field_type) {
$_ = $prng->fieldType($_);
if (
(substr($orig_item, -1) eq '`') ||
(substr($orig_item, 0, 2) eq "b'") ||
(substr($orig_item, 0, 2) eq '0x')
) {
# Do not quote, quotes are already present
} elsif (index($_, "'") > -1) {
$_ = '"'.$_.'"';
} else {
$_ = "'".$_."'";
}
} elsif (substr($_, 0, 1) eq '_') {
$item_nodash = substr($_, 1);
if ($prng->isFieldType($item_nodash)) {
$_ = "'".$prng->fieldType($item_nodash)."'";
if (index($_, "'") > -1) {
$_ = '"'.$_.'"';
} else {
$_ = "'".$_."'";
}
}
}

# If the grammar initially contained a ` , restore it. This allows
# The generation of constructs such as `table _digit` => `table 5`

if (
(substr($orig_item, -1) eq '`') &&
(index($_, '`') == -1)
) {
$_ = $_.'`';
}

$invariants{$orig_item} = $_ if $modifier eq 'invariant';
}

Hardcoded RQG constants

Июнь 16th, 2012 | Posted by self in Pensieve | Testing - (Комментарии отключены)

There are some important RQG constants that sometimes need to be changed to make particular tests more reasonable. Maybe some day I’ll make them configurable, but so far I just modify them in the code. Since it doesn’t happen every day, I tend to forget where they are located, so here they are:

For performance comparison test (new values can be different depending on the nature of the test):

lib/GenTest/Validator/ExecutionTimeComparator.pm

# Configurable constants:
-use constant MIN_DURATION   => 0.02;  # (seconds) Queries with shorter execution times are not processed.
+use constant MIN_DURATION   => 0.2;  # (seconds) Queries with shorter execution times are not processed.
use constant MAX_DURATION   => 300;   # (seconds) Queries with longer execution times are not processed.
-use constant MIN_RATIO      => 1.5;   # Minimum speed-up or slow-down required in order to report a query
+use constant MIN_RATIO      => 5;   # Minimum speed-up or slow-down required in order to report a query
use constant MAX_ROWS       => 200;   # Skip query if initial execution resulted in more than so many rows.
use constant MIN_SAMPLES    => 0;     # Minimum number of execution time samples to do for each query per server.
use constant MAX_SAMPLES    => 0;     # Max number of execution time samples per query per server. Must be no less than MIN_SAMPLES.

For result comparison tests, where queries too often fail due to reaching max rows threshold:

lib/GenTest/Executor/MySQL.pm
-use constant MAX_ROWS_THRESHOLD => 50000;
+use constant MAX_ROWS_THRESHOLD => 500000;

For running experimental combinations, to avoid aborting a set of tests prematurely due to an error which RQG considers an environment failure, make STATUS_ENVIRONMENT_FAILURE not fatal:

lib/GenTest/Constants.pm
-use constant STATUS_ENVIRONMENT_FAILURE => 110; # A failure in the environment or the grammar file
+use constant STATUS_ENVIRONMENT_FAILURE => 90; # A failure in the environment or the grammar file

For creating less tables than it’s usually done by default (but not bothering to create your own zz file just yet):

=== modified file 'lib/GenTest/App/GendataSimple.pm'
-use constant GDS_DEFAULT_NAMES => ['A', 'B', 'C', 'D', 'E', 'AA', 'BB', 'CC', 'DD'];
+use constant GDS_DEFAULT_NAMES => ['A', 'B', 'C', 'D'];