--source include/have_innodb.inc # The embedded server tests do not support restarting. --source include/not_embedded.inc --source include/have_debug.inc --source include/have_debug_sync.inc FLUSH TABLES; let INNODB_PAGE_SIZE=`select @@innodb_page_size`; let MYSQLD_DATADIR=`select @@datadir`; --echo # --echo # MDEV-11369: Instant ADD COLUMN for InnoDB --echo # CREATE TABLE t1(id INT PRIMARY KEY, c2 INT UNIQUE) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; CREATE TABLE t2 LIKE t1; INSERT INTO t1 VALUES(0,2); INSERT INTO t2 VALUES(2,1); ALTER TABLE t2 ADD COLUMN (c3 TEXT NOT NULL DEFAULT 'De finibus bonorum'); BEGIN; INSERT INTO t2 VALUES(3,4,'accusantium doloremque laudantium'); connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; --send ALTER TABLE t1 ADD COLUMN (c3 TEXT NOT NULL DEFAULT ' et malorum'); connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; COMMIT; --source include/kill_mysqld.inc disconnect ddl; --source include/start_mysqld.inc SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SELECT * FROM t1; SELECT * FROM t2; BEGIN; DELETE FROM t1; ROLLBACK; --source include/wait_all_purged.inc INSERT INTO t2 VALUES (16,1551,'Omnium enim rerum'),(128,1571,' principia parva sunt'); BEGIN; UPDATE t1 SET c2=c2+1; connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; --send ALTER TABLE t2 DROP COLUMN c3, ADD COLUMN c5 TEXT DEFAULT 'naturam abhorrere'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; COMMIT; --source include/kill_mysqld.inc disconnect ddl; --source include/start_mysqld.inc SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SELECT * FROM t1; SELECT * FROM t2; BEGIN; INSERT INTO t1 SET id=1; DELETE FROM t2; ROLLBACK; --source include/wait_all_purged.inc INSERT INTO t2 VALUES (64,42,'De finibus bonorum'), (347,33101,' et malorum'); BEGIN; DELETE FROM t1; connect ddl, localhost, root; ALTER TABLE t2 DROP COLUMN c3; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; --send ALTER TABLE t2 ADD COLUMN (c4 TEXT NOT NULL DEFAULT ' et malorum'); connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; COMMIT; --source include/kill_mysqld.inc disconnect ddl; --source include/start_mysqld.inc SET GLOBAL innodb_purge_rseg_truncate_frequency=1; let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; let SEARCH_PATTERN= \[Note\] InnoDB: Rolled back recovered transaction ; -- source include/search_pattern_in_file.inc SELECT * FROM t1; SELECT * FROM t2; BEGIN; INSERT INTO t1 SET id=1; DELETE FROM t2; ROLLBACK; --source include/wait_all_purged.inc FLUSH TABLE t1,t2 FOR EXPORT; # At this point, t1 is empty and t2 contains a 'default row'. # The following is based on innodb.table_flags and innodb.dml_purge: --perl use strict; my $ps= $ENV{INNODB_PAGE_SIZE}; foreach my $table ('t1','t2') { my $file= "$ENV{MYSQLD_DATADIR}/test/$table.ibd"; open(FILE, "<", $file) || die "Unable to open $file\n"; my $page; sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file"; die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps; print "$table clustered index root page"; print "(type ", unpack("n", substr($page,24,2)), "):\n"; print "N_RECS=", unpack("n", substr($page,38+16,2)); print "; LEVEL=", unpack("n", substr($page,38+26,2)), "\n"; my @fields=("id","DB_TRX_ID","DB_ROLL_PTR", "c2","c3","c4"); for (my $offset= 0x65; $offset; $offset= unpack("n", substr($page,$offset-2,2))) { print "header=0x", unpack("H*",substr($page,$offset-6,6)), " ("; my $n_fields= unpack("n", substr($page,$offset-4,2)) >> 1 & 0x3ff; my $start= 0; my $name; if (unpack("C", substr($page,$offset-3,1)) & 1) { for (my $i= 0; $i < $n_fields; $i++) { my $end= unpack("C", substr($page, $offset-7-$i, 1)); print ",\n " if $i; print "$fields[$i]="; if ($end & 0x80) { print "NULL(", ($end & 0x7f) - $start, " bytes)" } else { print "0x", unpack("H*", substr($page,$offset+$start,$end-$start)) } $start= $end & 0x7f; } } else { for (my $i= 0; $i < $n_fields; $i++) { my $end= unpack("n", substr($page, $offset-8-2*$i, 2)); print ",\n " if $i; if ($i > 2 && !(~unpack("C",substr($page,$offset-6,1)) & 0x30)) { if ($i == 3) { print "BLOB="; $start += 8; # skip the space_id,page_number } else { print "$fields[$i - 1]="; } } else { print "$fields[$i]="; } if ($end & 0x8000) { print "NULL(", ($end & 0x7fff) - $start, " bytes)" } else { print "0x", unpack("H*", substr($page,$offset+$start,($end-$start) & 0x3fff)) } $start= $end & 0x3fff; } } print ")\n"; } close(FILE) || die "Unable to close $file\n"; } EOF UNLOCK TABLES; DELETE FROM t2; --source include/wait_all_purged.inc --echo # --echo # MDEV-24323 Crash on recovery after kill during instant ADD COLUMN --echo # BEGIN; INSERT INTO t1 VALUES(0,0); connect ddl, localhost, root; CREATE TABLE t3(id INT PRIMARY KEY, c2 INT, v2 INT AS(c2) VIRTUAL, UNIQUE(v2)) ENGINE=InnoDB; INSERT INTO t3 SET id=1,c2=1; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; --send ALTER TABLE t3 ADD COLUMN c3 TEXT NOT NULL DEFAULT 'sic transit gloria mundi'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; COMMIT; --source include/kill_mysqld.inc disconnect ddl; --source include/start_mysqld.inc SHOW CREATE TABLE t1; SHOW CREATE TABLE t2; SHOW CREATE TABLE t3; DROP TABLE t2,t3; --echo # --echo # MDEV-29440 InnoDB instant ALTER TABLE recovery wrongly uses --echo # READ COMMITTED isolation level instead of READ UNCOMMITTED --echo # CREATE TABLE t2(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6); BEGIN; DELETE FROM t1; connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; --send ALTER TABLE t2 ADD COLUMN b TINYINT UNSIGNED NOT NULL DEFAULT 42 FIRST; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; COMMIT; --source include/kill_mysqld.inc disconnect ddl; --source include/start_mysqld.inc CHECK TABLE t2; DROP TABLE t1,t2; --list_files $MYSQLD_DATADIR/test