Commit e67b1070 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-17049 Enable innodb_undo tests on buildbot

Remove the innodb_undo suite, and move and adapt the tests.
Remove unnecessary restarts, and add innodb_page_size_small.inc
for combinations.

innodb.undo_truncate is the merge of innodb_undo.truncate
and innodb_undo.truncate_multi_client.

Add the global status variable innodb_undo_truncations.
Without this, the test innodb.undo_truncate would occasionally
report that truncation did not happen. The test was only waiting
for the history list length to reach 0, but the undo tablespace
truncation would only take place some time after that.

Undo tablespace truncation will only occasionally occur with
innodb_page_size=32k, and typically never occur (with this amount
of undo log operations) with innodb_page_size=64k. We disable
these combinations.

innodb.undo_truncate_recover was formerly called
innodb_undo.truncate_recover.
parent 055a3334
call mtr.add_suppression("InnoDB: The transaction log size is too large"); call mtr.add_suppression("InnoDB: The transaction log size is too large");
SET GLOBAL innodb_fast_shutdown=0; SET @save_undo_logs = @@GLOBAL.innodb_undo_logs;
SET @save_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET @save_truncate = @@GLOBAL.innodb_undo_log_truncate;
SET GLOBAL innodb_undo_log_truncate = 0;
SET GLOBAL innodb_undo_logs = 4;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
SET @trunc_start=
(SELECT variable_value FROM information_schema.global_status
WHERE variable_name = 'innodb_undo_truncations');
create table t1(keyc int primary key, c char(100)) engine = innodb; create table t1(keyc int primary key, c char(100)) engine = innodb;
create table t2(keyc int primary key, c char(100)) engine = innodb; create table t2(keyc int primary key, c char(100)) engine = innodb;
CREATE PROCEDURE populate_t1() CREATE PROCEDURE populate_t1()
...@@ -37,6 +45,7 @@ delete from t1; ...@@ -37,6 +45,7 @@ delete from t1;
connection con2; connection con2;
delete from t2; delete from t2;
connection con1; connection con1;
SET GLOBAL innodb_undo_log_truncate = 1;
commit; commit;
disconnect con1; disconnect con1;
connection con2; connection con2;
...@@ -46,7 +55,7 @@ connection default; ...@@ -46,7 +55,7 @@ connection default;
drop table t1, t2; drop table t1, t2;
drop PROCEDURE populate_t1; drop PROCEDURE populate_t1;
drop PROCEDURE populate_t2; drop PROCEDURE populate_t2;
SET GLOBAL innodb_fast_shutdown=0; InnoDB 0 transactions not purged
SET GLOBAL innodb_undo_log_truncate=1; SET GLOBAL innodb_undo_logs = @save_undo_logs;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
FOUND 1 /Truncating UNDO tablespace 1/ in mysqld.1.err SET GLOBAL innodb_undo_log_truncate = @save_truncate;
#
# WL#6965: Truncate UNDO logs.
#
--source include/have_innodb.inc --source include/have_innodb.inc
# This test is restarting the server. # With 32k, truncation could happen on shutdown after the test,
--source include/not_embedded.inc # and the mtr.add_suppression() would not filter out the warning.
# With larger innodb_page_size, the undo log tablespaces do not grow enough. # With 64k, no truncation seems to happen.
--source include/have_innodb_max_16k.inc # --source include/innodb_page_size.inc
--source include/innodb_page_size_small.inc
--source include/have_undo_tablespaces.inc --source include/have_undo_tablespaces.inc
call mtr.add_suppression("InnoDB: The transaction log size is too large"); call mtr.add_suppression("InnoDB: The transaction log size is too large");
SET GLOBAL innodb_fast_shutdown=0;
--let $restart_parameters=--innodb_undo_tablespaces=2 --innodb_undo_logs=4 SET @save_undo_logs = @@GLOBAL.innodb_undo_logs;
--source include/restart_mysqld.inc SET @save_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET @save_truncate = @@GLOBAL.innodb_undo_log_truncate;
SET GLOBAL innodb_undo_log_truncate = 0;
SET GLOBAL innodb_undo_logs = 4;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
SET @trunc_start=
(SELECT variable_value FROM information_schema.global_status
WHERE variable_name = 'innodb_undo_truncations');
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# #
...@@ -45,6 +50,7 @@ END | ...@@ -45,6 +50,7 @@ END |
delimiter ;| delimiter ;|
# #
# #
let DATADIR = `select @@datadir`;
connect (con1,localhost,root,,); connect (con1,localhost,root,,);
begin; begin;
send call populate_t1(); send call populate_t1();
...@@ -58,21 +64,65 @@ connection con2; reap; send update t2 set c = 'mysql'; ...@@ -58,21 +64,65 @@ connection con2; reap; send update t2 set c = 'mysql';
connection con1; reap; send update t1 set c = 'oracle'; connection con1; reap; send update t1 set c = 'oracle';
connection con2; reap; send update t2 set c = 'oracle'; connection con2; reap; send update t2 set c = 'oracle';
connection con1; reap; send delete from t1; connection con1; reap; send delete from t1;
connection con2; reap; send delete from t2; connection con2; reap; delete from t2;
connection con1; reap; commit; disconnect con1; connection con1; reap;
connection con2; reap; commit; disconnect con2;
let CHECKFILE = $MYSQL_TMP_DIR/check.txt;
perl;
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size1)
= stat("$ENV{DATADIR}/undo001");
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size2)
= stat("$ENV{DATADIR}/undo002");
open(OUT, ">$ENV{CHECKFILE}") || die;
print OUT "let \$size1='$size1,$size2';\n";
close(OUT);
EOF
SET GLOBAL innodb_undo_log_truncate = 1;
commit; disconnect con1;
connection con2; commit; disconnect con2;
connection default; connection default;
drop table t1, t2; drop table t1, t2;
drop PROCEDURE populate_t1; drop PROCEDURE populate_t1;
drop PROCEDURE populate_t2; drop PROCEDURE populate_t2;
SET GLOBAL innodb_fast_shutdown=0; --source include/wait_all_purged.inc
SET GLOBAL innodb_undo_log_truncate=1;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1; # Truncation will normally not occur with innodb_page_size=64k,
# and occasionally not with innodb_page_size=32k,
# because the undo log will not grow enough.
if (`select @@innodb_page_size IN (4096,8192,16384)`)
{
let $wait_condition = (SELECT variable_value!=@trunc_start
FROM information_schema.global_status
WHERE variable_name = 'innodb_undo_truncations');
source include/wait_condition.inc;
}
--source $CHECKFILE
perl;
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size1)
= stat("$ENV{DATADIR}/undo001");
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size2)
= stat("$ENV{DATADIR}/undo002");
open(OUT, ">$ENV{CHECKFILE}") || die;
print OUT "let \$size2='$size1,$size2';\n";
close(OUT);
EOF
--source $CHECKFILE
--remove_file $CHECKFILE
--source include/restart_mysqld.inc if ($size1 == $size2)
{
# This fails for innodb_page_size=64k, occasionally also for 32k.
if (`select @@innodb_page_size IN (4096,8192,16384)`)
{
echo Truncation did not happen: $size1;
}
}
let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err; SET GLOBAL innodb_undo_logs = @save_undo_logs;
let SEARCH_PATTERN = Truncating UNDO tablespace 1; SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
--source include/search_pattern_in_file.inc SET GLOBAL innodb_undo_log_truncate = @save_truncate;
call mtr.add_suppression("InnoDB: The transaction log size is too large");
SET GLOBAL innodb_fast_shutdown=0;
create table t1(keyc int primary key, c1 char(100)) engine = innodb;
begin;
update t1 set c1 = 'mysql';
update t1 set c1 = 'oracle';
delete from t1;
commit;
drop table t1;
SET GLOBAL innodb_fast_shutdown=0;
SET GLOBAL innodb_undo_log_truncate=1;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
#
# WL#6965: Truncate UNDO logs.
#
--source include/have_innodb.inc
--source include/have_innodb_max_16k.inc
--source include/have_undo_tablespaces.inc
# The test is restarting the server to force undo truncation.
--source include/not_embedded.inc
call mtr.add_suppression("InnoDB: The transaction log size is too large");
SET GLOBAL innodb_fast_shutdown=0;
--let $restart_parameters=--innodb_undo_tablespaces=2 --innodb_undo_logs=4
--source include/restart_mysqld.inc
let MYSQLD_DATADIR = `select @@datadir`;
#-----------------------------------------------------------------------------
#
# 1. Perform enough DML action so that undo tablespace size grows beyond
# set threshold and then wait and see if it is being truncated.
#
create table t1(keyc int primary key, c1 char(100)) engine = innodb;
begin;
--disable_query_log
let $i=30000;
while ($i) {
eval insert into t1 values(30000-$i, '');
dec $i;
}
--enable_query_log
update t1 set c1 = 'mysql';
update t1 set c1 = 'oracle';
delete from t1;
commit;
drop table t1;
let CHECKFILE = $MYSQL_TMP_DIR/check.txt;
perl;
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size1)
= stat("$ENV{MYSQLD_DATADIR}/undo001");
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size2)
= stat("$ENV{MYSQLD_DATADIR}/undo002");
open(OUT, ">$ENV{CHECKFILE}") || die;
print OUT "let \$size1='$size1,$size2';\n";
close(OUT);
EOF
SET GLOBAL innodb_fast_shutdown=0;
SET GLOBAL innodb_undo_log_truncate=1;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
--source include/shutdown_mysqld.inc
--source $CHECKFILE
perl;
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size1)
= stat("$ENV{MYSQLD_DATADIR}/undo001");
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size2)
= stat("$ENV{MYSQLD_DATADIR}/undo002");
open(OUT, ">$ENV{CHECKFILE}") || die;
print OUT "let \$size2='$size1,$size2';\n";
close(OUT);
EOF
--source $CHECKFILE
--remove_file $CHECKFILE
if ($size1 == $size2)
{
echo Truncation did not happen: $size1 == $size2;
}
--let $restart_parameters=
--source include/start_mysqld.inc
...@@ -1100,6 +1100,8 @@ static SHOW_VAR innodb_status_variables[]= { ...@@ -1100,6 +1100,8 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_truncated_status_writes, SHOW_LONG}, (char*) &export_vars.innodb_truncated_status_writes, SHOW_LONG},
{"available_undo_logs", {"available_undo_logs",
(char*) &export_vars.innodb_available_undo_logs, SHOW_LONG}, (char*) &export_vars.innodb_available_undo_logs, SHOW_LONG},
{"undo_truncations",
(char*) &export_vars.innodb_undo_truncations, SHOW_LONG},
/* Status variables for page compression */ /* Status variables for page compression */
{"page_compression_saved", {"page_compression_saved",
......
...@@ -1022,6 +1022,8 @@ struct export_var_t{ ...@@ -1022,6 +1022,8 @@ struct export_var_t{
ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */ ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */
ulint innodb_available_undo_logs; /*!< srv_available_undo_logs ulint innodb_available_undo_logs; /*!< srv_available_undo_logs
*/ */
/** Number of undo tablespace truncation operations */
ulong innodb_undo_truncations;
ulint innodb_defragment_compression_failures; /*!< Number of ulint innodb_defragment_compression_failures; /*!< Number of
defragment re-compression defragment re-compression
failures */ failures */
......
...@@ -1076,6 +1076,9 @@ trx_purge_initiate_truncate( ...@@ -1076,6 +1076,9 @@ trx_purge_initiate_truncate(
os_file_truncate(file->name, file->handle, os_file_truncate(file->name, file->handle,
os_offset_t(size) << srv_page_size_shift, true); os_offset_t(size) << srv_page_size_shift, true);
/* This is only executed by the srv_coordinator_thread. */
export_vars.innodb_undo_truncations++;
/* TODO: PUNCH_HOLE the garbage (with write-ahead logging) */ /* TODO: PUNCH_HOLE the garbage (with write-ahead logging) */
mutex_enter(&fil_system->mutex); mutex_enter(&fil_system->mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment