diff --git a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.opt b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.opt new file mode 100644 index 00000000000..20a4e60b8ec --- /dev/null +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.opt @@ -0,0 +1 @@ +--skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/include/innodb_wl6501_crash.inc b/mysql-test/suite/innodb/include/innodb_wl6501_crash.inc new file mode 100644 index 00000000000..93eca7ec060 --- /dev/null +++ b/mysql-test/suite/innodb/include/innodb_wl6501_crash.inc @@ -0,0 +1,416 @@ +# +# WL#6501: make truncate table atomic +# + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +# suppress expected warnings. +call mtr.add_suppression("The file '.*' already exists though the corresponding table did not exist in the InnoDB data dictionary"); +call mtr.add_suppression("Cannot create file '.*'"); +call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'"); + +################################################################################ +# +# Will test following scenarios: +# 1. Hit crash point while writing redo log. +# 2. Hit crash point on completion of redo log write. +# 3. Hit crash point while dropping indexes. +# 4. Hit crash point on completing drop of all indexes before creation of index +# is commenced. +# 5. Hit crash point while creating indexes. +# 6. Hit crash point after data is updated to system-table and in-memory dict. +# 7. Hit crash point before/after log checkpoint is done. +# +################################################################################ + +#----------------------------------------------------------------------------- +# +# create test-bed +# +let $per_table = `select @@innodb_file_per_table`; + +eval set global innodb_file_per_table = on; +let $WL6501_TMP_DIR = `select @@tmpdir`; +let $WL6501_DATA_DIR = `select @@datadir`; +let SEARCH_FILE = $MYSQLTEST_VARDIR/log/my_restart.err; + +#----------------------------------------------------------------------------- +# +# 1. Hit crash point while writing redo log. +# +--echo "1. Hit crash point while writing redo log." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine=innodb row_format=$wl6501_row_fmt + key_block_size=$wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_while_writing_redo_log"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 2. Hit crash point on completion of redo log write. +# +--echo "2. Hit crash point on completion of redo log write." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 3. Hit crash point while dropping indexes. +# +--echo "3. Hit crash point while dropping indexes." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_drop_of_clust_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; +# +# +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_drop_of_uniq_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +# +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; +# +# +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_drop_of_sec_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 4. Hit crash point on completing drop of all indexes before creation of index +# is commenced. +# +--echo "4. Hit crash point on completing drop of all indexes before creation" +--echo " of index is commenced." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 5. Hit crash point while creating indexes. +# +--echo "5. Hit crash point while creating indexes." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_create_of_clust_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; +# +# +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_create_of_uniq_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; +# +# +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_create_of_sec_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 6. Hit crash point after data is updated to system-table and in-memory dict. +# +--echo "6. Hit crash point after data is updated to system-table and" +--echo " in-memory dict." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 7. Hit crash point before/after log checkpoint is done. +# +--echo "7. Hit crash point before/after log checkpoint is done." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_before_log_removal"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t where f < 2.5; +drop table t; +# +# +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_after_truncate_done"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + + +#----------------------------------------------------------------------------- +# +# remove test-bed +# +eval set global innodb_file_per_table = $per_table; diff --git a/mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc b/mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc new file mode 100644 index 00000000000..edec93b875c --- /dev/null +++ b/mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc @@ -0,0 +1,98 @@ +# +# WL#6501: make truncate table atomic +# + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +# suppress expected warnings +call mtr.add_suppression("does not exist in the InnoDB internal"); + +################################################################################ +# +# Will test following scenarios: +# 1. Hit crash point on completing drop of all indexes before creation of index +# is commenced. +# 2. Hit crash point after data is updated to system-table and in-memory dict. +# +################################################################################ + +#----------------------------------------------------------------------------- +# +# create test-bed +# +let $per_table = `select @@innodb_file_per_table`; + +eval set global innodb_file_per_table = on; +let $WL6501_TMP_DIR = `select @@tmpdir`; +let $WL6501_DATA_DIR = `select @@datadir`; +let SEARCH_FILE = $MYSQLTEST_VARDIR/log/my_restart.err; + +#----------------------------------------------------------------------------- +# +# 1. Hit crash point on completing drop of all indexes before creation of index +# is commenced. +# +--echo "1. Hit crash point on completing drop of all indexes before creation" +--echo " of index is commenced." +eval set global innodb_file_per_table = $wl6501_file_per_table; +set innodb_strict_mode=off; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; + +#----------------------------------------------------------------------------- +# +# 2. Hit crash point after data is updated to system-table and in-memory dict. +# +--echo "2. Hit crash point after data is updated to system-table and" +--echo " in-memory dict." +eval set global innodb_file_per_table = $wl6501_file_per_table; +set innodb_strict_mode=off; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; + +#----------------------------------------------------------------------------- +# +# remove test-bed +# +eval set global innodb_file_per_table = $per_table; diff --git a/mysql-test/suite/innodb/include/truncate_recover.inc b/mysql-test/suite/innodb/include/truncate_recover.inc new file mode 100644 index 00000000000..fe068afa6e3 --- /dev/null +++ b/mysql-test/suite/innodb/include/truncate_recover.inc @@ -0,0 +1,8 @@ +begin; +update t1 set c = 'MariaDB'; +update t1 set c = 'InnoDB'; +eval set global debug_dbug = '+d,$SEARCH_PATTERN'; +commit; +--source include/shutdown_mysqld.inc +--source include/search_pattern_in_file.inc +--source include/start_mysqld.inc diff --git a/mysql-test/suite/innodb/r/truncate_debug.result b/mysql-test/suite/innodb/r/truncate_debug.result new file mode 100644 index 00000000000..c04b83dbbe8 --- /dev/null +++ b/mysql-test/suite/innodb/r/truncate_debug.result @@ -0,0 +1,88 @@ +# +# Bug #23070734 CONCURRENT TRUNCATE TABLES CAUSE STALLS +# +SET @ahi= @@global.innodb_adaptive_hash_index; +SET GLOBAL innodb_adaptive_hash_index=OFF; +SET GLOBAL innodb_adaptive_hash_index=ON; +Test_1 :- Check if DDL operations are possible on +table being truncated. Also check if +DDL operations on other tables succeed. +create table t1 (f1 int,f2 int,key(f2),f3 int) engine=innodb; +create index idx1 on t1(f3); +create table t2 (f1 int,f2 int,key(f2),f3 int) engine=innodb; +create table t3 (f1 int,f2 int,key(f2)) engine=innodb; +insert into t1 values (10,20,30),(30,40,50),(50,60,70); +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t2 values (10,20,30),(30,40,50),(50,60,70); +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t3 values (10,20),(30,40),(50,50); +insert into t3 select * from t3; +insert into t3 select * from t3; +SET session lock_wait_timeout = 1; +connect con1,localhost,root,,; +SET DEBUG_SYNC= 'buffer_pool_scan SIGNAL started WAIT_FOR finish_scan'; +truncate table t1; +connection default; +SET DEBUG_SYNC= 'now WAIT_FOR started'; +Check Analyze table. Gives lock time out error. +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze Error Lock wait timeout exceeded; try restarting transaction +test.t1 analyze status Operation failed +Check if we can turn off auto recalculation. +alter table t1 STATS_AUTO_RECALC=0; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check if we can turn off persistent stats on the table +alter table t1 STATS_PERSISTENT=0; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check if DML is possible on table being truncated +insert into t1 values (10,89,99); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check if DDL is possible on table being truncated +alter table t1 add column f4 int; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +check if table can be created with the same name +create table t1 (bd int) engine=innodb; +Got one of the listed errors +check if index can be created on table being truncated +create index idx1 on t1(f1); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check if DROP of table is possible during truncate +drop table t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check if select is possible during truncate +select * from t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t2 where t2.f1=t1.f1; +ERROR 42S22: Unknown column 't1.f1' in 'where clause' +Check concurrent truncate operation on table; +truncate table t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check concurrent selects and inserts on the other table +insert into t3 values (10,20),(30,40),(50,50); +select * from t3 where f1=40; +f1 f2 +Concurrent truncate on other tables +truncate table t2; +Concurrent alters on the other tables +alter table t2 add column f4 int; +check if index can be created on the other table +create index idx1 on t2(f3); +Check if we can turn off persistent stats off entire instance +SET GLOBAL innodb_stats_persistent=off; +connect con2,localhost,root,,; +set global innodb_adaptive_hash_index=off; +connection default; +SET DEBUG_SYNC= 'now SIGNAL finish_scan'; +connection con1; +disconnect con1; +connection con2; +disconnect con2; +connection default; +SET DEBUG_SYNC= 'RESET'; +SET GLOBAL innodb_adaptive_hash_index=@ahi; +drop table t1,t2,t3; diff --git a/mysql-test/suite/innodb/r/truncate_inject.result b/mysql-test/suite/innodb/r/truncate_inject.result new file mode 100644 index 00000000000..5ec532a0f83 --- /dev/null +++ b/mysql-test/suite/innodb/r/truncate_inject.result @@ -0,0 +1,114 @@ +SET @save_dbug = @@SESSION.debug_dbug; +call mtr.add_suppression("InnoDB: Flagged corruption of .* in table `test`\\.`t` in TRUNCATE TABLE"); +# 1. Error in assigning undo logs for truncate action +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; +Table Op Msg_type Msg_text +test.t check status OK +SET debug_dbug = '+d,ib_err_trunc_assigning_undo_log'; +truncate table t; +ERROR HY000: Got error 168 "Unknown (generic) error from engine" from storage engine InnoDB +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +# 2. Error while preparing for truncate +SET debug_dbug = '+d,ib_err_trunc_preparing_for_truncate'; +truncate table t; +ERROR HY000: Got error 168 "Unknown (generic) error from engine" from storage engine InnoDB +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +# 3. Error while dropping/creating indexes +SET debug_dbug = '+d,ib_err_trunc_drop_index'; +truncate table t; +ERROR HY000: Got error 168 "Unknown (generic) error from engine" from storage engine InnoDB +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check Warning InnoDB: Index PRIMARY is marked as corrupted +test.t check error Corrupt +select * from t; +Got one of the listed errors +drop table t; +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; +Table Op Msg_type Msg_text +test.t check status OK +SET debug_dbug = '+d,ib_err_trunc_create_index'; +truncate table t; +ERROR HY000: Got error 168 "Unknown (generic) error from engine" from storage engine InnoDB +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check Warning InnoDB: Index PRIMARY is marked as corrupted +test.t check error Corrupt +select * from t; +Got one of the listed errors +drop table t; +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; +Table Op Msg_type Msg_text +test.t check status OK +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +drop table t; +# 4. Error while completing truncate of table involving FTS +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), +FULLTEXT INDEX(c)) ENGINE = InnoDB; +insert into t values (1, 1.1, 'mysql is now oracle company'), +(2, 2.2, 'innodb is part of mysql'), +(3, 3.3, 'innodb is default storage engine of mysql'); +check table t; +Table Op Msg_type Msg_text +test.t check status OK +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +drop table t; +# 5. Error while updating sys-tables +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), +FULLTEXT INDEX(c)) ENGINE = InnoDB; +insert into t values (1, 1.1, 'mysql is now oracle company'), +(2, 2.2, 'innodb is part of mysql'), +(3, 3.3, 'innodb is default storage engine of mysql'); +check table t; +Table Op Msg_type Msg_text +test.t check status OK +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t order by i; +i f c +drop table t; diff --git a/mysql-test/suite/innodb/r/truncate_purge_debug.result b/mysql-test/suite/innodb/r/truncate_purge_debug.result new file mode 100644 index 00000000000..164987083d5 --- /dev/null +++ b/mysql-test/suite/innodb/r/truncate_purge_debug.result @@ -0,0 +1,29 @@ +# +# Bug #23070734 CONCURRENT TRUNCATE TABLES CAUSE STALLS +# +create table t1 (f1 int ,f2 int,key(f2)) engine=innodb; +begin; +insert into t1 values (10,45),(20,78),(30,88),(40,23),(50,78),(60,11),(70,56),(80,90); +delete from t1; +connect con2,localhost,root,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +commit; +connect con1,localhost,root,,; +SET DEBUG_SYNC= 'buffer_pool_scan SIGNAL started WAIT_FOR finish_scan'; +truncate table t1; +connection con2; +SET DEBUG_SYNC= 'now WAIT_FOR started'; +COMMIT; +disconnect con2; +connection default; +InnoDB 0 transactions not purged +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; +SET DEBUG_SYNC = 'now SIGNAL finish_scan'; +connection con1; +disconnect con1; +connection default; +SET DEBUG_SYNC = 'RESET'; +drop table t1; diff --git a/mysql-test/suite/innodb/r/truncate_restart.result b/mysql-test/suite/innodb/r/truncate_restart.result new file mode 100644 index 00000000000..b6d14124371 --- /dev/null +++ b/mysql-test/suite/innodb/r/truncate_restart.result @@ -0,0 +1,12 @@ +SET GLOBAL innodb_stats_persistent= ON; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB STATS_PERSISTENT=1; +connect con1,localhost,root,,test; +SET DEBUG_SYNC='ib_trunc_table_trunc_completing SIGNAL committed WAIT_FOR ever'; +TRUNCATE TABLE t1; +connection default; +SET DEBUG_SYNC='now WAIT_FOR committed'; +disconnect con1; +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/alter_copy.opt b/mysql-test/suite/innodb/t/alter_copy.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/alter_copy.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/alter_crash.opt b/mysql-test/suite/innodb/t/alter_crash.opt index 39b93371503..96710441921 100644 --- a/mysql-test/suite/innodb/t/alter_crash.opt +++ b/mysql-test/suite/innodb/t/alter_crash.opt @@ -1 +1,2 @@ --loose-innodb-sys-tables +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/drop_table_background.opt b/mysql-test/suite/innodb/t/drop_table_background.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/drop_table_background.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/rename_table_debug.opt b/mysql-test/suite/innodb/t/rename_table_debug.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/rename_table_debug.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/truncate.opt b/mysql-test/suite/innodb/t/truncate.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/truncate_crash.opt b/mysql-test/suite/innodb/t/truncate_crash.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_crash.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/truncate_debug.test b/mysql-test/suite/innodb/t/truncate_debug.test new file mode 100644 index 00000000000..5fee9174d98 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_debug.test @@ -0,0 +1,127 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--source include/count_sessions.inc + +--echo # +--echo # Bug #23070734 CONCURRENT TRUNCATE TABLES CAUSE STALLS +--echo # + +SET @ahi= @@global.innodb_adaptive_hash_index; +# Ensure that there is no adaptive hash index on any system tables, +# or any other tables than the ones that we are creating below. +SET GLOBAL innodb_adaptive_hash_index=OFF; +SET GLOBAL innodb_adaptive_hash_index=ON; + +--echo Test_1 :- Check if DDL operations are possible on +--echo table being truncated. Also check if +--echo DDL operations on other tables succeed. + +create table t1 (f1 int,f2 int,key(f2),f3 int) engine=innodb; +create index idx1 on t1(f3); +create table t2 (f1 int,f2 int,key(f2),f3 int) engine=innodb; +create table t3 (f1 int,f2 int,key(f2)) engine=innodb; + +insert into t1 values (10,20,30),(30,40,50),(50,60,70); +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t2 values (10,20,30),(30,40,50),(50,60,70); + +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; + +insert into t3 values (10,20),(30,40),(50,50); +insert into t3 select * from t3; +insert into t3 select * from t3; + +SET session lock_wait_timeout = 1; + +connect (con1,localhost,root,,); +SET DEBUG_SYNC= 'buffer_pool_scan SIGNAL started WAIT_FOR finish_scan'; +send truncate table t1; + +connection default; +SET DEBUG_SYNC= 'now WAIT_FOR started'; + +--echo Check Analyze table. Gives lock time out error. +analyze table t1; + +--echo Check if we can turn off auto recalculation. +--error ER_LOCK_WAIT_TIMEOUT +alter table t1 STATS_AUTO_RECALC=0; + +--echo Check if we can turn off persistent stats on the table +--error ER_LOCK_WAIT_TIMEOUT +alter table t1 STATS_PERSISTENT=0; + +--echo Check if DML is possible on table being truncated +--error ER_LOCK_WAIT_TIMEOUT +insert into t1 values (10,89,99); + +--echo Check if DDL is possible on table being truncated +--error ER_LOCK_WAIT_TIMEOUT +alter table t1 add column f4 int; + +--echo check if table can be created with the same name +--error ER_TABLE_EXISTS_ERROR,ER_LOCK_WAIT_TIMEOUT +create table t1 (bd int) engine=innodb; + +--echo check if index can be created on table being truncated +--error ER_LOCK_WAIT_TIMEOUT +create index idx1 on t1(f1); + +--echo Check if DROP of table is possible during truncate +--error ER_LOCK_WAIT_TIMEOUT +drop table t1; + +--echo Check if select is possible during truncate +--error ER_LOCK_WAIT_TIMEOUT +select * from t1; + +--error ER_BAD_FIELD_ERROR +select * from t2 where t2.f1=t1.f1; + +--echo Check concurrent truncate operation on table; +--error ER_LOCK_WAIT_TIMEOUT +truncate table t1; + +--echo Check concurrent selects and inserts on the other table +insert into t3 values (10,20),(30,40),(50,50); +select * from t3 where f1=40; + +--echo Concurrent truncate on other tables +truncate table t2; + +--echo Concurrent alters on the other tables +alter table t2 add column f4 int; + +--echo check if index can be created on the other table +create index idx1 on t2(f3); + +--echo Check if we can turn off persistent stats off entire instance +SET GLOBAL innodb_stats_persistent=off; + +connect (con2,localhost,root,,); +send set global innodb_adaptive_hash_index=off; + +connection default; +SET DEBUG_SYNC= 'now SIGNAL finish_scan'; + +connection con1; +reap; +disconnect con1; + +connection con2; +reap; +disconnect con2; + +connection default; +SET DEBUG_SYNC= 'RESET'; + +SET GLOBAL innodb_adaptive_hash_index=@ahi; + +drop table t1,t2,t3; +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/truncate_foreign.opt b/mysql-test/suite/innodb/t/truncate_foreign.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_foreign.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/truncate_inject.test b/mysql-test/suite/innodb/t/truncate_inject.test new file mode 100644 index 00000000000..35e516324bb --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_inject.test @@ -0,0 +1,97 @@ +# This test is based on innodb_zip.wl6501_error_1 in MySQL 5.7. + +--source include/have_innodb.inc +--source include/innodb_row_format.inc +--source include/have_debug.inc + +SET @save_dbug = @@SESSION.debug_dbug; + +call mtr.add_suppression("InnoDB: Flagged corruption of .* in table `test`\\.`t` in TRUNCATE TABLE"); + +--echo # 1. Error in assigning undo logs for truncate action +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; +# +SET debug_dbug = '+d,ib_err_trunc_assigning_undo_log'; +--error ER_GET_ERRNO +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +select * from t; + +--echo # 2. Error while preparing for truncate +SET debug_dbug = '+d,ib_err_trunc_preparing_for_truncate'; +--error ER_GET_ERRNO +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +select * from t; + +--echo # 3. Error while dropping/creating indexes +SET debug_dbug = '+d,ib_err_trunc_drop_index'; +--error ER_GET_ERRNO +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +--error ER_TABLE_CORRUPT,ER_GET_ERRNO +select * from t; +drop table t; + +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; + +SET debug_dbug = '+d,ib_err_trunc_create_index'; +--error ER_GET_ERRNO +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +--error ER_TABLE_CORRUPT,ER_GET_ERRNO +select * from t; +drop table t; + +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; + +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; + +check table t; +select * from t; +drop table t; + +--echo # 4. Error while completing truncate of table involving FTS +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), +FULLTEXT INDEX(c)) ENGINE = InnoDB; +insert into t values (1, 1.1, 'mysql is now oracle company'), + (2, 2.2, 'innodb is part of mysql'), + (3, 3.3, 'innodb is default storage engine of mysql'); +check table t; +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; + +check table t; +select * from t; +drop table t; + +--echo # 5. Error while updating sys-tables +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), +FULLTEXT INDEX(c)) ENGINE = InnoDB; +insert into t values (1, 1.1, 'mysql is now oracle company'), + (2, 2.2, 'innodb is part of mysql'), + (3, 3.3, 'innodb is default storage engine of mysql'); +check table t; +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; + +check table t; +select * from t order by i; +drop table t; diff --git a/mysql-test/suite/innodb/t/truncate_missing.opt b/mysql-test/suite/innodb/t/truncate_missing.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_missing.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/truncate_purge_debug.opt b/mysql-test/suite/innodb/t/truncate_purge_debug.opt new file mode 100644 index 00000000000..8bed7e46166 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_purge_debug.opt @@ -0,0 +1,3 @@ +--innodb-purge-threads=1 +--innodb-purge-batch-size=1 +--innodb-stats-persistent=OFF diff --git a/mysql-test/suite/innodb/t/truncate_purge_debug.test b/mysql-test/suite/innodb/t/truncate_purge_debug.test new file mode 100644 index 00000000000..e8f5768f557 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_purge_debug.test @@ -0,0 +1,49 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/count_sessions.inc + +--echo # +--echo # Bug #23070734 CONCURRENT TRUNCATE TABLES CAUSE STALLS +--echo # + +create table t1 (f1 int ,f2 int,key(f2)) engine=innodb; +begin; +insert into t1 values (10,45),(20,78),(30,88),(40,23),(50,78),(60,11),(70,56),(80,90); +delete from t1; + +connect (con2,localhost,root,,); +# Stop the purge thread +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +# Ensure that the history list length will actually be decremented by purge. +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +commit; + +connect (con1,localhost,root,,); +SET DEBUG_SYNC= 'buffer_pool_scan SIGNAL started WAIT_FOR finish_scan'; +send truncate table t1; + +connection con2; +SET DEBUG_SYNC= 'now WAIT_FOR started'; +# Allow purge to proceed, by discarding our read view. +COMMIT; +disconnect con2; + +connection default; +--source include/wait_all_purged.inc + +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; + +SET DEBUG_SYNC = 'now SIGNAL finish_scan'; + +connection con1; +reap; +disconnect con1; + +connection default; +SET DEBUG_SYNC = 'RESET'; +drop table t1; +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/truncate_restart.test b/mysql-test/suite/innodb/t/truncate_restart.test new file mode 100644 index 00000000000..60a3d83cd81 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_restart.test @@ -0,0 +1,16 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +SET GLOBAL innodb_stats_persistent= ON; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB STATS_PERSISTENT=1; +--connect (con1,localhost,root,,test) +SET DEBUG_SYNC='ib_trunc_table_trunc_completing SIGNAL committed WAIT_FOR ever'; +--send +TRUNCATE TABLE t1; +--connection default +SET DEBUG_SYNC='now WAIT_FOR committed'; +--source include/restart_mysqld.inc +--disconnect con1 +SELECT COUNT(*) FROM t1; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc b/mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc new file mode 100644 index 00000000000..bef28a9c484 --- /dev/null +++ b/mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc @@ -0,0 +1,112 @@ +# +# load tables with some significant amount of data and then truncate it. +# + +#----------------------------------------------------------------------------- +# +# create test-bed +# +let $per_table = `select @@innodb_file_per_table`; +let $format = `select @@innodb_file_format`; + +let $WL6501_TMP_DIR = `select @@tmpdir`; +let $WL6501_DATA_DIR = `select @@datadir`; +set innodb_strict_mode=OFF; + +#----------------------------------------------------------------------------- +# +# create procedure to load data +# +delimiter |; +create procedure populate() +begin + declare i int default 1; + while (i <= 5000) do + insert into t1 values (i, 'a', 'b'); + insert into t2 values (i, 'a', 'b'); + insert into t3 values (i, 'a', 'b'); + set i = i + 1; + end while; +end| +create procedure populate_small() +begin + declare i int default 10001; + while (i <= 12000) do + insert into t1 values (i, 'c', 'd'); + insert into t2 values (i, 'a', 'b'); + insert into t3 values (i, 'a', 'b'); + set i = i + 1; + end while; +end| +delimiter ;| + +#----------------------------------------------------------------------------- +# +# create and load the tables. +# +eval set global innodb_file_per_table = $wl6501_file_per_table; +--replace_regex /[0-9]+/NUMBER/ +eval create table t1 + (i int, c1 char(100), c2 char(100), + index c1_idx(c1)) + engine=innodb row_format=$wl6501_row_fmt + key_block_size=$wl6501_kbs; +eval create table t2 + (i int, c1 char(100), c2 char(100), + index c1_idx(c1)) + engine=innodb row_format=$wl6501_row_fmt + key_block_size=$wl6501_kbs; +eval create temporary table t3 + (i int, c1 char(100), c2 char(100), + index c1_idx(c1)) + engine=innodb row_format=$wl6501_row_fmt + key_block_size=$wl6501_kbs; +# +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +begin; +call populate(); +commit; +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +# +truncate table t1; +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +# +call populate_small(); +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +# +truncate table t2; +truncate table t3; +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +# +call populate_small(); +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +# +drop table t1; +drop table t2; +drop table t3; + +#----------------------------------------------------------------------------- +# +# drop the procedure +# +drop procedure populate; +drop procedure populate_small; + +#----------------------------------------------------------------------------- +# +# remove test-bed +# +eval set global innodb_file_format = $format; +eval set global innodb_file_per_table = $per_table; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_1.result b/mysql-test/suite/innodb_zip/r/wl6501_1.result new file mode 100644 index 00000000000..bf901804be5 --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/wl6501_1.result @@ -0,0 +1,1202 @@ +set global innodb_file_per_table=on; +# Verify that 'TRUNCATE TABLE' statement works fine and the size +# of .ibd file is equal to the initial size after truncation. +drop table if exists t1,t2,t3,t4,t6; +Warnings: +Note 1051 Unknown table 'test.t1' +Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t3' +Note 1051 Unknown table 'test.t4' +Note 1051 Unknown table 'test.t6' +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_during_drop_index_temp_table"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_during_drop_index_temp_table point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t5; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_drop_of_sec_index point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_drop_of_sec_index point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_drop_of_sec_index point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_drop_of_sec_index point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_drop_reinit_done_create_to_start---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t5; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_create_of_sec_index---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_create_of_sec_index---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_create_of_sec_index---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_create_of_sec_index---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_before_log_removal point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_before_log_removal point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_before_log_removal point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_before_log_removal point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_redo_log_write_complete point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_redo_log_write_complete point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_redo_log_write_complete point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_redo_log_write_complete point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_crash_3.result b/mysql-test/suite/innodb_zip/r/wl6501_crash_3.result new file mode 100644 index 00000000000..554bb2892f6 --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/wl6501_crash_3.result @@ -0,0 +1,462 @@ +call mtr.add_suppression("The file '.*' already exists though the corresponding table did not exist in the InnoDB data dictionary"); +call mtr.add_suppression("Cannot create file '.*'"); +call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'"); +set global innodb_file_per_table = on; +"1. Hit crash point while writing redo log." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine=innodb row_format=compressed +key_block_size=16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_while_writing_redo_log"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"2. Hit crash point on completion of redo log write." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"3. Hit crash point while dropping indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"4. Hit crash point on completing drop of all indexes before creation" +" of index is commenced." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"5. Hit crash point while creating indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"6. Hit crash point after data is updated to system-table and" +" in-memory dict." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"7. Hit crash point before/after log checkpoint is done." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_crash_4.result b/mysql-test/suite/innodb_zip/r/wl6501_crash_4.result new file mode 100644 index 00000000000..d766ecceaac --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/wl6501_crash_4.result @@ -0,0 +1,519 @@ +call mtr.add_suppression("The file '.*' already exists though the corresponding table did not exist in the InnoDB data dictionary"); +call mtr.add_suppression("Cannot create file '.*'"); +call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'"); +set global innodb_file_per_table = on; +"1. Hit crash point while writing redo log." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine=innodb row_format=compressed +key_block_size=4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_while_writing_redo_log"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"2. Hit crash point on completion of redo log write." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"3. Hit crash point while dropping indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"4. Hit crash point on completing drop of all indexes before creation" +" of index is commenced." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"5. Hit crash point while creating indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"6. Hit crash point after data is updated to system-table and" +" in-memory dict." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"7. Hit crash point before/after log checkpoint is done." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +set global innodb_file_per_table = 1; +call mtr.add_suppression("does not exist in the InnoDB internal"); +set global innodb_file_per_table = on; +"1. Hit crash point on completing drop of all indexes before creation" +" of index is commenced." +set global innodb_file_per_table = 1; +set innodb_strict_mode=off; +create temporary table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check Error Table 'test.t' doesn't exist +test.t check status Operation failed +"2. Hit crash point after data is updated to system-table and" +" in-memory dict." +set global innodb_file_per_table = 1; +set innodb_strict_mode=off; +create temporary table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check Error Table 'test.t' doesn't exist +test.t check status Operation failed +set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_crash_5.result b/mysql-test/suite/innodb_zip/r/wl6501_crash_5.result new file mode 100644 index 00000000000..b5fea6382ff --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/wl6501_crash_5.result @@ -0,0 +1,462 @@ +call mtr.add_suppression("The file '.*' already exists though the corresponding table did not exist in the InnoDB data dictionary"); +call mtr.add_suppression("Cannot create file '.*'"); +call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'"); +set global innodb_file_per_table = on; +"1. Hit crash point while writing redo log." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine=innodb row_format=compressed +key_block_size=8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_while_writing_redo_log"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"2. Hit crash point on completion of redo log write." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"3. Hit crash point while dropping indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"4. Hit crash point on completing drop of all indexes before creation" +" of index is commenced." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"5. Hit crash point while creating indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"6. Hit crash point after data is updated to system-table and" +" in-memory dict." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"7. Hit crash point before/after log checkpoint is done." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result b/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result new file mode 100644 index 00000000000..3a74b6ebc11 --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result @@ -0,0 +1,345 @@ +set innodb_strict_mode=OFF; +create procedure populate() +begin +declare i int default 1; +while (i <= 5000) do +insert into t1 values (i, 'a', 'b'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +create procedure populate_small() +begin +declare i int default 10001; +while (i <= 12000) do +insert into t1 values (i, 'c', 'd'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +set global innodb_file_per_table = 1; +create table tNUMBER +(i int, cNUMBER char(NUMBER), cNUMBER char(NUMBER), +index cNUMBER_idx(cNUMBER)) +engine=innodb row_format=compact +key_block_size=NUMBER; +Warnings: +Warning NUMBER InnoDB: ignoring KEY_BLOCK_SIZE=NUMBER unless ROW_FORMAT=COMPRESSED. +create table t2 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compact +key_block_size=16; +Warnings: +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16 unless ROW_FORMAT=COMPRESSED. +create temporary table t3 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compact +key_block_size=16; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +begin; +call populate(); +commit; +select count(*) from t1; +count(*) +5000 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +truncate table t1; +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +call populate_small(); +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +7000 +select count(*) from t3; +count(*) +7000 +truncate table t2; +truncate table t3; +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +call populate_small(); +select count(*) from t1; +count(*) +4000 +select count(*) from t2; +count(*) +2000 +select count(*) from t3; +count(*) +2000 +drop table t1; +drop table t2; +drop table t3; +drop procedure populate; +drop procedure populate_small; +set global innodb_file_format = Barracuda; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See https://mariadb.com/kb/en/library/xtradbinnodb-file-format/ +set global innodb_file_per_table = 1; +set innodb_strict_mode=OFF; +create procedure populate() +begin +declare i int default 1; +while (i <= 5000) do +insert into t1 values (i, 'a', 'b'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +create procedure populate_small() +begin +declare i int default 10001; +while (i <= 12000) do +insert into t1 values (i, 'c', 'd'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +set global innodb_file_per_table = 1; +create table tNUMBER +(i int, cNUMBER char(NUMBER), cNUMBER char(NUMBER), +index cNUMBER_idx(cNUMBER)) +engine=innodb row_format=compressed +key_block_size=NUMBER; +create table t2 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compressed +key_block_size=16; +create temporary table t3 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compressed +key_block_size=16; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +begin; +call populate(); +commit; +select count(*) from t1; +count(*) +5000 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +truncate table t1; +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +call populate_small(); +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +7000 +select count(*) from t3; +count(*) +7000 +truncate table t2; +truncate table t3; +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +call populate_small(); +select count(*) from t1; +count(*) +4000 +select count(*) from t2; +count(*) +2000 +select count(*) from t3; +count(*) +2000 +drop table t1; +drop table t2; +drop table t3; +drop procedure populate; +drop procedure populate_small; +set global innodb_file_format = Barracuda; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See https://mariadb.com/kb/en/library/xtradbinnodb-file-format/ +set global innodb_file_per_table = 1; +set innodb_strict_mode=OFF; +create procedure populate() +begin +declare i int default 1; +while (i <= 5000) do +insert into t1 values (i, 'a', 'b'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +create procedure populate_small() +begin +declare i int default 10001; +while (i <= 12000) do +insert into t1 values (i, 'c', 'd'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +set global innodb_file_per_table = 0; +create table tNUMBER +(i int, cNUMBER char(NUMBER), cNUMBER char(NUMBER), +index cNUMBER_idx(cNUMBER)) +engine=innodb row_format=compact +key_block_size=NUMBER; +Warnings: +Warning NUMBER InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning NUMBER InnoDB: ignoring KEY_BLOCK_SIZE=NUMBER. +create table t2 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compact +key_block_size=16; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +create temporary table t3 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compact +key_block_size=16; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +begin; +call populate(); +commit; +select count(*) from t1; +count(*) +5000 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +truncate table t1; +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +call populate_small(); +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +7000 +select count(*) from t3; +count(*) +7000 +truncate table t2; +truncate table t3; +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +call populate_small(); +select count(*) from t1; +count(*) +4000 +select count(*) from t2; +count(*) +2000 +select count(*) from t3; +count(*) +2000 +drop table t1; +drop table t2; +drop table t3; +drop procedure populate; +drop procedure populate_small; +set global innodb_file_format = Barracuda; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See https://mariadb.com/kb/en/library/xtradbinnodb-file-format/ +set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/t/restart.opt b/mysql-test/suite/innodb_zip/t/restart.opt index 52314cbf241..fd89db6cc1d 100644 --- a/mysql-test/suite/innodb_zip/t/restart.opt +++ b/mysql-test/suite/innodb_zip/t/restart.opt @@ -1,3 +1,4 @@ --loose-innodb-sys-tables --loose-innodb-sys-tablespaces --loose-innodb-sys-datafiles +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb_zip/t/wl6501_1.test b/mysql-test/suite/innodb_zip/t/wl6501_1.test new file mode 100644 index 00000000000..dd8b5f65b31 --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/wl6501_1.test @@ -0,0 +1,451 @@ + +#################################################################### +# TC to check truncate table statement atomicity for single # +# tablespace # +# Sceanrio covered: # +# 1. Debug points added for worklog # +# 2. Table with differnt row types # +# 3. Transactional statement. # +#################################################################### + + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc +--source include/have_innodb_16k.inc + +# Valgrind would result in a "long semaphore wait" inside InnoDB +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +#----------------------------------------------------------------------- +--disable_query_log +let $MYSQL_DATA_DIR= `select @@datadir`; +let $data_directory = data directory='$MYSQL_TMP_DIR/alt_dir'; +let $innodb_file_per_table_orig=`select @@innodb_file_per_table`; + +call mtr.add_suppression("InnoDB.*table did not exist in the InnoDB data dictionary.*"); +call mtr.add_suppression("InnoDB: A page in the doublewrite buffer is not within space bounds.*"); +call mtr.add_suppression("InnoDB: Cannot create file.*"); +call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'.*"); +call mtr.add_suppression("InnoDB: A page in the doublewrite buffer is not within space bounds"); +call mtr.add_suppression("InnoDB: Error: table .* does not exist in the InnoDB internal"); +--enable_query_log + +#----------------------------------------------------------------------- +set global innodb_file_per_table=on; +--echo # Verify that 'TRUNCATE TABLE' statement works fine and the size +--echo # of .ibd file is equal to the initial size after truncation. + +#----------------------------------------------------------------------- +drop table if exists t1,t2,t3,t4,t6; +let $cnt = 6; +while ($cnt) { + + # table with basic data type + primary ,secondary,composite,prefix index + create table t1(c1 int not null, + c2 int not null, + c3 char(255) not null, + c4 text(500) not null, + c5 blob(500) not null, + c6 varchar(500) not null, + c7 varchar(500) not null, + c8 datetime, + c9 decimal(5,3), + primary key (c1), + index (c3,c4(50),c5(50)), + index (c2)) + engine=innodb row_format=redundant; + + + create table t2(c1 int not null, + c2 int not null, + c3 char(255) not null, + c4 text(500) not null, + c5 blob(500) not null, + c6 varchar(500) not null, + c7 varchar(500) not null, + c8 datetime, + c9 decimal(5,3), + primary key (c1), + index (c3,c4(50),c5(50)), + index (c2)) + engine=innodb row_format=compact; + + + # with row type , key block size = 4K + create table t3(c1 int not null, + c2 int not null, + c3 char(255) not null, + c4 text(500) not null, + c5 blob(500) not null, + c6 varchar(500) not null, + c7 varchar(500) not null, + c8 datetime, + c9 decimal(5,3), + primary key (c1), + index (c3,c4(50),c5(50)), + index (c2)) + engine=innodb row_format=compressed key_block_size=4; + + + create table t4(c1 int not null, + c2 int not null, + c3 char(255) not null, + c4 text(500) not null, + c5 blob(500) not null, + c6 varchar(500) not null, + c7 varchar(500) not null, + c8 datetime, + c9 decimal(5,3), + primary key (c1), + index (c3,c4(50),c5(50)), + index (c2)) + engine=innodb row_format=dynamic; + + + create temporary table t5(c1 int not null, + c2 int not null, + c3 char(255) not null, + c4 text(500) not null, + c5 blob(500) not null, + c6 varchar(500) not null, + c7 varchar(500) not null, + c8 datetime, + c9 decimal(5,3), + primary key (c1), + index (c3,c4(50),c5(50)), + index (c2)) + engine=innodb; + + create table t6 ( a int ) engine = innodb; + insert into t6 values (50),(100),(150); + + --disable_query_log + --disable_result_log + let $n=5; + + # load created tables. + while ($n) + { + start transaction; + + eval insert ignore into t1 values( + $n, $n, + repeat(concat(' tc3_',$n), 42), + repeat(concat(' tc4_',$n), 300), + repeat(concat(' tc5_',$n), 300), + repeat(concat(' tc6_',$n), 300), + repeat(concat(' tc7_',$n), 300), + now(), (100.55+$n)); + + eval insert ignore into t2 values( + $n, $n, + repeat(concat(' tc3_',$n), 42), + repeat(concat(' tc4_',$n), 300), + repeat(concat(' tc5_',$n), 300), + repeat(concat(' tc6_',$n), 300), + repeat(concat(' tc7_',$n), 300), + now(), (100.55+$n)); + + eval insert ignore into t3 values( + $n, $n, + repeat(concat(' tc3_',$n), 42), + repeat(concat(' tc4_',$n), 300), + repeat(concat(' tc5_',$n), 300), + repeat(concat(' tc6_',$n), 300), + repeat(concat(' tc7_',$n), 300), + now(), (100.55+$n)); + + eval insert ignore into t4 values( + $n, $n, + repeat(concat(' tc3_',$n), 42), + repeat(concat(' tc4_',$n), 300), + repeat(concat(' tc5_',$n), 300), + repeat(concat(' tc6_',$n), 300), + repeat(concat(' tc7_',$n), 300), + now(), (100.55+$n)); + + eval insert ignore into t5 values( + $n, $n, + repeat(concat(' tc3_',$n), 42), + repeat(concat(' tc4_',$n), 300), + repeat(concat(' tc5_',$n), 300), + repeat(concat(' tc6_',$n), 300), + repeat(concat(' tc7_',$n), 300), + now(), (100.55+$n)); + + if ($n <= 3) + { + commit; + } + + if ($n > 3) + { + rollback; + } + + dec $n; + } + + # validate loading of the tables. + --enable_result_log + --enable_query_log + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + select count(*) from t5; + select count(*) from t6; + + # set the debug crash point and exercise them. + if ($cnt == 6) + { + set session debug="+d,ib_trunc_crash_during_drop_index_temp_table"; + --echo "---debug ib_trunc_crash_during_drop_index_temp_table point---" + } + if ($cnt == 5) + { + set session debug="+d,ib_trunc_crash_drop_reinit_done_create_to_start"; + --echo "---debug ib_trunc_crash_drop_reinit_done_create_to_start---" + } + + if ($cnt >= 5) { + --echo # Write file to make mysql-test-run.pl expect crash and restart + --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --echo # Run the crashing query + --error 2013 + truncate table t5; + --source include/wait_until_disconnected.inc + --enable_reconnect + --echo # Restart the MySQL server + --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --source include/wait_until_connected_again.inc + --disable_reconnect + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + --error ER_NO_SUCH_TABLE + select count(*) from t5; + select count(*) from t6; + } + + # set the debug crash point and exercise them. + if ($cnt == 6) + { + set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; + --echo "---debug ib_trunc_crash_on_drop_of_sec_index point---" + } + if ($cnt == 5) + { + set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; + --echo "---debug ib_trunc_crash_on_create_of_sec_index---" + } + if ($cnt == 4) + { + set session debug="+d,ib_trunc_crash_before_log_removal"; + --echo "---debug ib_trunc_crash_before_log_removal point---" + } + if ($cnt == 3) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 2) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 1) + { + set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; + --echo "---debug ib_trunc_crash_after_redo_log_write_complete point---" + } + + --echo # Write file to make mysql-test-run.pl expect crash and restart + --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --echo # Run the crashing query + --error 2013 + truncate table t1; + --source include/wait_until_disconnected.inc + --enable_reconnect + --echo # Restart the MySQL server + --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --source include/wait_until_connected_again.inc + --disable_reconnect + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + --error ER_NO_SUCH_TABLE + select count(*) from t5; + select count(*) from t6; + + if ($cnt == 6) + { + set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; + --echo "---debug ib_trunc_crash_on_drop_of_sec_index point---" + } + if ($cnt == 5) + { + set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; + --echo "---debug ib_trunc_crash_on_create_of_sec_index---" + } + if ($cnt == 4) + { + set session debug="+d,ib_trunc_crash_before_log_removal"; + --echo "---debug ib_trunc_crash_before_log_removal point---" + } + if ($cnt == 3) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 2) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 1) + { + set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; + --echo "---debug ib_trunc_crash_after_redo_log_write_complete point---" + } + + + --echo # Write file to make mysql-test-run.pl expect crash and restart + --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --echo # Run the crashing query + --error 2013 + truncate table t2; + --source include/wait_until_disconnected.inc + --enable_reconnect + --echo # Restart the MySQL server + --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --source include/wait_until_connected_again.inc + --disable_reconnect + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + --error ER_NO_SUCH_TABLE + select count(*) from t5; + select count(*) from t6; + + if ($cnt == 6) + { + set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; + --echo "---debug ib_trunc_crash_on_drop_of_sec_index point---" + } + if ($cnt == 5) + { + set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; + --echo "---debug ib_trunc_crash_on_create_of_sec_index---" + } + if ($cnt == 4) + { + set session debug="+d,ib_trunc_crash_before_log_removal"; + --echo "---debug ib_trunc_crash_before_log_removal point---" + } + if ($cnt == 3) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 2) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 1) + { + set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; + --echo "---debug ib_trunc_crash_after_redo_log_write_complete point---" + } + + + --echo # Write file to make mysql-test-run.pl expect crash and restart + --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --echo # Run the crashing query + --error 2013 + truncate table t3; + --source include/wait_until_disconnected.inc + --enable_reconnect + --echo # Restart the MySQL server + --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --source include/wait_until_connected_again.inc + --disable_reconnect + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + --error ER_NO_SUCH_TABLE + select count(*) from t5; + select count(*) from t6; + + + if ($cnt == 6) + { + set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; + --echo "---debug ib_trunc_crash_on_drop_of_sec_index point---" + } + if ($cnt == 5) + { + set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; + --echo "---debug ib_trunc_crash_on_create_of_sec_index---" + } + if ($cnt == 4) + { + set session debug="+d,ib_trunc_crash_before_log_removal"; + --echo "---debug ib_trunc_crash_before_log_removal point---" + } + if ($cnt == 3) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 2) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 1) + { + set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; + --echo "---debug ib_trunc_crash_after_redo_log_write_complete point---" + } + + --echo # Write file to make mysql-test-run.pl expect crash and restart + --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --echo # Run the crashing query + --error 2013 + truncate table t4; + --source include/wait_until_disconnected.inc + --enable_reconnect + --echo # Restart the MySQL server + --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --source include/wait_until_connected_again.inc + --disable_reconnect + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + --error ER_NO_SUCH_TABLE + select count(*) from t5; + select count(*) from t6; + + drop table t1, t2, t3, t4, t6; + + dec $cnt; + + --disable_query_log + eval set global innodb_file_per_table=$innodb_file_per_table_orig; + --enable_query_log +} + + + diff --git a/mysql-test/suite/innodb_zip/t/wl6501_crash_3.test b/mysql-test/suite/innodb_zip/t/wl6501_crash_3.test new file mode 100644 index 00000000000..3ec990b4715 --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/wl6501_crash_3.test @@ -0,0 +1,25 @@ +# +# WL#6501: make truncate table atomic +# + +# TC tries to hit crash point during truncate of +# compressed non-temp table residing in single tablespace +# with page-size=16k + +--source include/have_innodb.inc +--source include/have_innodb_16k.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +let $wl6501_file_per_table = 1; +let $wl6501_row_fmt = compressed; +let $wl6501_kbs = 16; +--source suite/innodb/include/innodb_wl6501_crash.inc + diff --git a/mysql-test/suite/innodb_zip/t/wl6501_crash_4.test b/mysql-test/suite/innodb_zip/t/wl6501_crash_4.test new file mode 100644 index 00000000000..f54df3c128c --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/wl6501_crash_4.test @@ -0,0 +1,27 @@ +# +# WL#6501: make truncate table atomic +# + +# TC tries to hit crash point during truncate of +# compressed non-temp table residing in single tablespace. +# with page-size=4k + +--source include/have_innodb.inc +--source include/have_innodb_4k.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +let $wl6501_file_per_table = 1; +let $wl6501_row_fmt = compressed; +let $wl6501_kbs = 4; +--source suite/innodb/include/innodb_wl6501_crash.inc + +let $wl6501_temp = temporary; +--source suite/innodb/include/innodb_wl6501_crash_temp.inc diff --git a/mysql-test/suite/innodb_zip/t/wl6501_crash_5.test b/mysql-test/suite/innodb_zip/t/wl6501_crash_5.test new file mode 100644 index 00000000000..2f9847ae5fb --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/wl6501_crash_5.test @@ -0,0 +1,25 @@ +# +# WL#6501: make truncate table atomic +# + +# TC tries to hit crash point during truncate of +# compressed non-temp table residing in single tablespace. +# with page-size=8k + +--source include/have_innodb.inc +--source include/have_innodb_8k.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +let $wl6501_file_per_table = 1; +let $wl6501_row_fmt = compressed; +let $wl6501_kbs = 8; +--source suite/innodb/include/innodb_wl6501_crash.inc + diff --git a/mysql-test/suite/innodb_zip/t/wl6501_scale_1.test b/mysql-test/suite/innodb_zip/t/wl6501_scale_1.test new file mode 100644 index 00000000000..e6392759d5e --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/wl6501_scale_1.test @@ -0,0 +1,37 @@ +# +# WL#6501: make truncate table atomic +# + +# load table with some significiant amount of data +# and then try truncate + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc +--source include/have_innodb_16k.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + + +# Single-Tablespace/Non-Compressed +let $wl6501_file_per_table = 1; +let $wl6501_row_fmt = compact; +let $wl6501_kbs = 16; +--source suite/innodb_zip/include/innodb_wl6501_scale.inc + +# Single-Tablespace/Compressed +let $wl6501_file_per_table = 1; +let $wl6501_row_fmt = compressed; +let $wl6501_kbs = 16; +--source suite/innodb_zip/include/innodb_wl6501_scale.inc + +# System-Tablespace/Non-Compressed +let $wl6501_file_per_table = 0; +let $wl6501_row_fmt = compact; +let $wl6501_kbs = 16; +--source suite/innodb_zip/include/innodb_wl6501_scale.inc diff --git a/mysql-test/suite/mariabackup/truncate_during_backup.opt b/mysql-test/suite/mariabackup/truncate_during_backup.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/mariabackup/truncate_during_backup.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index a82fa3ff5bc..0673de0054a 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2974,6 +2974,20 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME INNODB_UNSAFE_TRUNCATE +SESSION_VALUE NULL +GLOBAL_VALUE ON +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE ON +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Use backup-unsafe TRUNCATE TABLE for compatibility with xtrabackup (on by default) +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY YES +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_USE_ATOMIC_WRITES SESSION_VALUE NULL GLOBAL_VALUE ON diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index 594528ccbb1..2f9419efc62 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -1140,6 +1140,73 @@ dict_recreate_index_tree( return(FIL_NULL); } +/*******************************************************************//** +Truncates the index tree but don't update SYSTEM TABLES. +@return DB_SUCCESS or error */ +dberr_t +dict_truncate_index_tree_in_mem( +/*============================*/ + dict_index_t* index) /*!< in/out: index */ +{ + mtr_t mtr; + bool truncate; + ulint space = index->space; + + ut_ad(mutex_own(&dict_sys->mutex)); + ut_ad(dict_table_is_temporary(index->table)); + + ulint type = index->type; + ulint root_page_no = index->page; + + if (root_page_no == FIL_NULL) { + + /* The tree has been freed. */ + ib::warn() << "Trying to TRUNCATE a missing index of table " + << index->table->name << "!"; + + truncate = false; + } else { + truncate = true; + } + + bool found; + const page_size_t page_size(fil_space_get_page_size(space, + &found)); + + if (!found) { + + /* It is a single table tablespace and the .ibd file is + missing: do nothing */ + + ib::warn() + << "Trying to TRUNCATE a missing .ibd file of table " + << index->table->name << "!"; + } + + /* If table to truncate resides in its on own tablespace that will + be re-created on truncate then we can ignore freeing of existing + tablespace objects. */ + + if (truncate) { + btr_free(page_id_t(space, root_page_no), page_size); + } + + mtr_start(&mtr); + mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); + + root_page_no = btr_create( + type, space, page_size, index->id, index, NULL, &mtr); + + DBUG_EXECUTE_IF("ib_err_trunc_temp_recreate_index", + root_page_no = FIL_NULL;); + + index->page = root_page_no; + + mtr_commit(&mtr); + + return(index->page == FIL_NULL ? DB_ERROR : DB_SUCCESS); +} + /*********************************************************************//** Creates a table create graph. @return own: table create node */ diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 28874154c16..368144fe2b2 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -3112,6 +3112,154 @@ void fil_truncate_log(fil_space_t* space, ulint size, mtr_t* mtr) NULL, space->flags & ~FSP_FLAGS_MEM_MASK, mtr); } +/** Truncate the tablespace to needed size. +@param[in] space_id id of tablespace to truncate +@param[in] size_in_pages truncate size. +@return true if truncate was successful. */ +bool +fil_truncate_tablespace( + ulint space_id, + ulint size_in_pages) +{ + /* Step-1: Prepare tablespace for truncate. This involves + stopping all the new operations + IO on that tablespace + and ensuring that related pages are flushed to disk. */ + if (fil_prepare_for_truncate(space_id) != DB_SUCCESS) { + return(false); + } + + /* Step-2: Invalidate buffer pool pages belonging to the tablespace + to re-create. Remove all insert buffer entries for the tablespace */ + buf_LRU_flush_or_remove_pages(space_id, NULL); + + /* Step-3: Truncate the tablespace and accordingly update + the fil_space_t handler that is used to access this tablespace. */ + mutex_enter(&fil_system->mutex); + fil_space_t* space = fil_space_get_by_id(space_id); + + /* The following code must change when InnoDB supports + multiple datafiles per tablespace. */ + ut_a(UT_LIST_GET_LEN(space->chain) == 1); + + fil_node_t* node = UT_LIST_GET_FIRST(space->chain); + + ut_ad(node->is_open()); + + space->size = node->size = size_in_pages; + + bool success = os_file_truncate(node->name, node->handle, 0); + if (success) { + + os_offset_t size = os_offset_t(size_in_pages) * UNIV_PAGE_SIZE; + + success = os_file_set_size( + node->name, node->handle, size, + FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags)); + + if (success) { + space->stop_new_ops = false; + space->is_being_truncated = false; + } + } + + mutex_exit(&fil_system->mutex); + + return(success); +} + +/*******************************************************************//** +Prepare for truncating a single-table tablespace. +1) Check pending operations on a tablespace; +2) Remove all insert buffer entries for the tablespace; +@return DB_SUCCESS or error */ +dberr_t +fil_prepare_for_truncate( +/*=====================*/ + ulint id) /*!< in: space id */ +{ + char* path = 0; + fil_space_t* space = 0; + + ut_a(!is_system_tablespace(id)); + + dberr_t err = fil_check_pending_operations( + id, FIL_OPERATION_TRUNCATE, &space, &path); + + ut_free(path); + + if (err == DB_TABLESPACE_NOT_FOUND) { + ib::error() << "Cannot truncate tablespace " << id + << " because it is not found in the tablespace" + " memory cache."; + } + + return(err); +} + +/** Reinitialize the original tablespace header with the same space id +for single tablespace +@param[in] table table belongs to tablespace +@param[in] size size in blocks +@param[in] trx Transaction covering truncate */ +void +fil_reinit_space_header_for_table( + dict_table_t* table, + ulint size, + trx_t* trx) +{ + ulint id = table->space; + + ut_a(!is_system_tablespace(id)); + + /* Invalidate in the buffer pool all pages belonging + to the tablespace. The buffer pool scan may take long + time to complete, therefore we release dict_sys->mutex + and the dict operation lock during the scan and aquire + it again after the buffer pool scan.*/ + + /* Release the lock on the indexes too. So that + they won't violate the latch ordering. */ + dict_table_x_unlock_indexes(table); + row_mysql_unlock_data_dictionary(trx); + + /* Lock the search latch in shared mode to prevent user + from disabling AHI during the scan */ + btr_search_s_lock_all(); + DEBUG_SYNC_C("buffer_pool_scan"); + buf_LRU_flush_or_remove_pages(id, NULL); + btr_search_s_unlock_all(); + + row_mysql_lock_data_dictionary(trx); + + dict_table_x_lock_indexes(table); + + /* Remove all insert buffer entries for the tablespace */ + ibuf_delete_for_discarded_space(id); + + mutex_enter(&fil_system->mutex); + + fil_space_t* space = fil_space_get_by_id(id); + + /* The following code must change when InnoDB supports + multiple datafiles per tablespace. */ + ut_a(UT_LIST_GET_LEN(space->chain) == 1); + + fil_node_t* node = UT_LIST_GET_FIRST(space->chain); + + space->size = node->size = size; + + mutex_exit(&fil_system->mutex); + + mtr_t mtr; + + mtr_start(&mtr); + mtr.set_named_space(id); + + fsp_header_init(id, size, &mtr); + + mtr_commit(&mtr); +} + #ifdef UNIV_DEBUG /** Increase redo skipped count for a tablespace. @param[in] id space id */ @@ -4971,6 +5119,7 @@ fil_io( if (space->id != TRX_SYS_SPACE && UT_LIST_GET_LEN(space->chain) == 1 && (srv_is_tablespace_truncated(space->id) + || space->is_being_truncated || srv_was_tablespace_truncated(space)) && req_type.is_read()) { @@ -5877,6 +6026,7 @@ truncate_t::truncate( } space->stop_new_ops = false; + space->is_being_truncated = false; /* If we opened the file in this function, close it. */ if (!already_open) { diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 6ddcff7a55a..d4d5abeb32f 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -639,6 +639,7 @@ fsp_space_modify_check( ut_ad(space->purpose == FIL_TYPE_TEMPORARY || space->purpose == FIL_TYPE_IMPORT || space->redo_skipped_count + || space->is_being_truncated || srv_is_tablespace_truncated(space->id)); return; case MTR_LOG_ALL: diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 49f51c78f73..26e169b1ec3 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13452,6 +13452,37 @@ int ha_innobase::truncate() update_thd(); + if (srv_57_truncate) { + if (!trx_is_started(m_prebuilt->trx)) { + ++m_prebuilt->trx->will_lock; + } + + dberr_t err = row_truncate_table_for_mysql( + m_prebuilt->table, m_prebuilt->trx); + + int error; + + switch (err) { + case DB_TABLESPACE_DELETED: + case DB_TABLESPACE_NOT_FOUND: + ib_senderrf( + m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, + err == DB_TABLESPACE_DELETED + ? ER_TABLESPACE_DISCARDED + : ER_TABLESPACE_MISSING, + table->s->table_name.str); + error = HA_ERR_TABLESPACE_MISSING; + break; + default: + error = convert_error_code_to_mysql( + err, m_prebuilt->table->flags, + m_prebuilt->trx->mysql_thd); + break; + } + table->status = STATUS_NOT_FOUND; + DBUG_RETURN(error); + } + HA_CREATE_INFO info; mem_heap_t* heap = mem_heap_create(1000); dict_table_t* ib_table = m_prebuilt->table; @@ -20663,6 +20694,11 @@ static MYSQL_SYSVAR_BOOL(read_only, srv_read_only_mode, "Start InnoDB in read only mode (off by default)", NULL, NULL, FALSE); +static MYSQL_SYSVAR_BOOL(unsafe_truncate, srv_57_truncate, + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, + "Use backup-unsafe TRUNCATE TABLE for compatibility with xtrabackup (on by default)", + NULL, NULL, TRUE); + static MYSQL_SYSVAR_BOOL(cmp_per_index_enabled, srv_cmp_per_index_enabled, PLUGIN_VAR_OPCMDARG, "Enable INFORMATION_SCHEMA.innodb_cmp_per_index," @@ -21042,6 +21078,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(random_read_ahead), MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(read_only), + MYSQL_SYSVAR(unsafe_truncate), MYSQL_SYSVAR(io_capacity), MYSQL_SYSVAR(io_capacity_max), MYSQL_SYSVAR(page_cleaners), diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h index e37ad66bc8c..5d149f24921 100644 --- a/storage/innobase/include/dict0crea.h +++ b/storage/innobase/include/dict0crea.h @@ -142,6 +142,14 @@ dict_create_index_tree_in_mem( dict_index_t* index, /*!< in/out: index */ const trx_t* trx); /*!< in: InnoDB transaction handle */ +/*******************************************************************//** +Truncates the index tree but don't update SYSTEM TABLES. +@return DB_SUCCESS or error */ +dberr_t +dict_truncate_index_tree_in_mem( +/*============================*/ + dict_index_t* index); /*!< in/out: index */ + /*******************************************************************//** Drops the index tree but don't update SYS_INDEXES table. */ void diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index c6b6ad92388..e738931485e 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -955,6 +955,37 @@ fil_space_t* fil_truncate_prepare(ulint space_id); void fil_truncate_log(fil_space_t* space, ulint size, mtr_t* mtr) MY_ATTRIBUTE((nonnull)); +/** Truncate the tablespace to needed size. +@param[in] space_id id of tablespace to truncate +@param[in] size_in_pages truncate size. +@return true if truncate was successful. */ +bool +fil_truncate_tablespace( + ulint space_id, + ulint size_in_pages); + +/*******************************************************************//** +Prepare for truncating a single-table tablespace. The tablespace +must be cached in the memory cache. +1) Check pending operations on a tablespace; +2) Remove all insert buffer entries for the tablespace; +@return DB_SUCCESS or error */ +dberr_t +fil_prepare_for_truncate( +/*=====================*/ + ulint id); /*!< in: space id */ + +/** Reinitialize the original tablespace header with the same space id +for single tablespace +@param[in] table table belongs to the tablespace +@param[in] size size in blocks +@param[in] trx Transaction covering truncate */ +void +fil_reinit_space_header_for_table( + dict_table_t* table, + ulint size, + trx_t* trx); + /*******************************************************************//** Closes a single-table tablespace. The tablespace must be cached in the memory cache. Free all pages used by the tablespace. diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 4759e5a85f4..4ff0056444b 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -519,7 +519,7 @@ roll back a retroactively introduced TRX_UNDO_RENAME_TABLE undo log record, MariaDB 10.2.18 and later will use the 10.3 format, but LOG_HEADER_SUBFORMAT 1 instead of 0. MariaDB 10.3 will use subformat 0 (5.7-style TRUNCATE) or 2 (MDEV-13564 backup-friendly TRUNCATE). */ -#define LOG_HEADER_FORMAT_CURRENT 103 +#define LOG_HEADER_FORMAT_10_3 103 /** The old MariaDB 10.2.2..10.2.17 log format */ #define LOG_HEADER_FORMAT_10_2 1 /** Future MariaDB 10.4 log format */ @@ -559,7 +559,7 @@ of log_sys->write_mutex, which should affect nothing for now. */ struct log_group_t{ /** number of files in the group */ ulint n_files; - /** format of the redo log: e.g., LOG_HEADER_FORMAT_CURRENT */ + /** format of the redo log: e.g., LOG_HEADER_FORMAT_10_3 */ uint32_t format; /** redo log subformat: 0 with separately logged TRUNCATE, 1 with fully redo-logged TRUNCATE */ diff --git a/storage/innobase/include/row0trunc.h b/storage/innobase/include/row0trunc.h index f9a20665a3b..4d6bdee225c 100644 --- a/storage/innobase/include/row0trunc.h +++ b/storage/innobase/include/row0trunc.h @@ -421,4 +421,9 @@ private: const char* log_file_name); }; +/** MySQL 5.7 TRUNCATE TABLE. +@param table table being truncated +@param trx transaction covering the truncate +@return error code or DB_SUCCESS */ +dberr_t row_truncate_table_for_mysql(dict_table_t* table, trx_t* trx); #endif /* row0trunc_h */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index ecd2914515d..f40cbf7f730 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -256,6 +256,9 @@ extern my_bool high_level_read_only; /** store to its own file each table created by an user; data dictionary tables are in the system tablespace 0 */ extern my_bool srv_file_per_table; +/** whether to use the MySQL 5.7 WL#6501 TRUNCATE TABLE implementation +that does not work with backup */ +extern my_bool srv_57_truncate; /** Sleep delay for threads waiting to enter InnoDB. In micro-seconds. */ extern ulong srv_thread_sleep_delay; /** Maximum sleep delay (in micro-seconds), value of 0 disables it.*/ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 95c637bccfd..b7d39440c75 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -790,10 +790,16 @@ log_init(ulint n_files) log_group_t* group = &log_sys->log; group->n_files = n_files; - group->format = srv_encrypt_log - ? LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED - : LOG_HEADER_FORMAT_CURRENT; - group->subformat = 1; + group->subformat = !srv_57_truncate; + if (srv_57_truncate) { + group->format = srv_encrypt_log + ? LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED + : LOG_HEADER_FORMAT_10_2; + } else { + group->format = srv_encrypt_log + ? LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED + : LOG_HEADER_FORMAT_10_3; + } group->file_size = srv_log_file_size; group->state = LOG_GROUP_OK; group->lsn = LOG_START_LSN; @@ -875,13 +881,15 @@ log_group_file_header_flush( ut_ad(!recv_no_log_write); ut_a(nth_file < group->n_files); ut_ad((group->format & ~LOG_HEADER_FORMAT_ENCRYPTED) - == LOG_HEADER_FORMAT_CURRENT); + == (srv_57_truncate + ? LOG_HEADER_FORMAT_10_2 + : LOG_HEADER_FORMAT_10_3)); buf = *(group->file_header_bufs + nth_file); memset(buf, 0, OS_FILE_LOG_BLOCK_SIZE); mach_write_to_4(buf + LOG_HEADER_FORMAT, group->format); - mach_write_to_4(buf + LOG_HEADER_SUBFORMAT, group->subformat); + mach_write_to_4(buf + LOG_HEADER_SUBFORMAT, !srv_57_truncate); mach_write_to_8(buf + LOG_HEADER_START_LSN, start_lsn); strcpy(reinterpret_cast(buf) + LOG_HEADER_CREATOR, LOG_HEADER_CREATOR_CURRENT); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 402e896ba15..2d2d9f2d674 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1165,10 +1165,10 @@ recv_find_max_checkpoint(ulint* max_field) switch (group->format) { case 0: return(recv_find_max_checkpoint_0(&group, max_field)); - case LOG_HEADER_FORMAT_CURRENT: - case LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED: case LOG_HEADER_FORMAT_10_2: case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED: + case LOG_HEADER_FORMAT_10_3: + case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: case LOG_HEADER_FORMAT_10_4: /* We can only parse the unencrypted LOG_HEADER_FORMAT_10_4. The encrypted format uses a larger redo log block trailer. */ @@ -1246,8 +1246,8 @@ recv_find_max_checkpoint(ulint* max_field) } switch (group->format) { - case LOG_HEADER_FORMAT_CURRENT: - case LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED: + case LOG_HEADER_FORMAT_10_3: + case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: if (group->subformat == 1) { /* 10.2 with new crash-safe TRUNCATE */ break; @@ -3431,8 +3431,8 @@ skip_apply: case LOG_HEADER_FORMAT_10_2: case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED: break; - case LOG_HEADER_FORMAT_CURRENT: - case LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED: + case LOG_HEADER_FORMAT_10_3: + case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: if (log_sys->log.subformat == 1) { /* 10.2 with new crash-safe TRUNCATE */ break; @@ -3769,6 +3769,7 @@ recv_recovery_rollback_active(void) /* Drop partially created indexes. */ row_merge_drop_temp_indexes(); /* Drop garbage tables. */ + if (!srv_57_truncate) row_mysql_drop_garbage_tables(); /* Drop any auxiliary tables that were not dropped when the diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 4423ec90dff..4e08377916d 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1629,7 +1629,8 @@ row_ins_check_foreign_constraint( if (check_table == NULL || !check_table->is_readable() - || check_index == NULL) { + || check_index == NULL + || fil_space_get(check_table->space)->is_being_truncated) { if (!srv_read_only_mode && check_ref) { FILE* ef = dict_foreign_err_file; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 1491921bece..5f558203ca4 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -4403,7 +4403,7 @@ row_rename_table_for_mysql( goto funct_exit; } - if (!table->is_temporary()) { + if (!table->is_temporary() && !srv_57_truncate) { err = trx_undo_report_rename(trx, table); if (err != DB_SUCCESS) { diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc index 79bffe498dd..c6c752a92b8 100644 --- a/storage/innobase/row/row0trunc.cc +++ b/storage/innobase/row/row0trunc.cc @@ -50,6 +50,8 @@ bool truncate_t::s_fix_up_active = false; truncate_t::tables_t truncate_t::s_tables; truncate_t::truncated_tables_t truncate_t::s_truncated_tables; +static const byte magic[] = { 0x01, 0xf3, 0xa1, 0x20 }; + /** Iterator over the the raw records in an index, doesn't support MVCC. */ class IndexIterator { @@ -240,6 +242,301 @@ protected: const bool m_noredo; }; +/** +Creates a TRUNCATE log record with space id, table name, data directory path, +tablespace flags, table format, index ids, index types, number of index fields +and index field information of the table. */ +class TruncateLogger : public Callback { + +public: + /** + Constructor + + @param table Table to truncate + @param flags tablespace falgs */ + TruncateLogger( + dict_table_t* table, + ulint flags, + table_id_t new_table_id) + : + Callback(table->id, false), + m_table(table), + m_flags(flags), + m_truncate(table->id, new_table_id, table->data_dir_path), + m_log_file_name() + { + /* Do nothing */ + } + + /** + Initialize Truncate Logger by constructing Truncate Log File Name. + + @return DB_SUCCESS or error code. */ + dberr_t init() + { + /* Construct log file name. */ + ulint log_file_name_buf_sz = + strlen(srv_log_group_home_dir) + + (22 + 22 + sizeof "ib_trunc.log"); + + m_log_file_name = UT_NEW_ARRAY_NOKEY(char, log_file_name_buf_sz); + if (m_log_file_name == NULL) { + return(DB_OUT_OF_MEMORY); + } + memset(m_log_file_name, 0, log_file_name_buf_sz); + + strcpy(m_log_file_name, srv_log_group_home_dir); + ulint log_file_name_len = strlen(m_log_file_name); + if (m_log_file_name[log_file_name_len - 1] + != OS_PATH_SEPARATOR) { + + m_log_file_name[log_file_name_len] + = OS_PATH_SEPARATOR; + log_file_name_len = strlen(m_log_file_name); + } + + snprintf(m_log_file_name + log_file_name_len, + log_file_name_buf_sz - log_file_name_len, + "ib_%u_" IB_ID_FMT "_trunc.log", + m_table->space, m_table->id); + + return(DB_SUCCESS); + + } + + /** + Destructor */ + ~TruncateLogger() + { + if (m_log_file_name != NULL) { + bool exist; + os_file_delete_if_exists( + innodb_log_file_key, m_log_file_name, &exist); + UT_DELETE_ARRAY(m_log_file_name); + m_log_file_name = NULL; + } + } + + /** + @param mtr mini-transaction covering the read + @param pcur persistent cursor used for reading + @return DB_SUCCESS or error code */ + dberr_t operator()(mtr_t* mtr, btr_pcur_t* pcur); + + /** Called after iteratoring over the records. + @return true if invariant satisfied. */ + bool debug() const + { + /* We must find all the index entries on disk. */ + return(UT_LIST_GET_LEN(m_table->indexes) + == m_truncate.indexes()); + } + + /** + Write the TRUNCATE log + @return DB_SUCCESS or error code */ + dberr_t log() const + { + dberr_t err = DB_SUCCESS; + + if (m_log_file_name == 0) { + return(DB_ERROR); + } + + bool ret; + os_file_t handle = os_file_create( + innodb_log_file_key, m_log_file_name, + OS_FILE_CREATE, OS_FILE_NORMAL, + OS_LOG_FILE, srv_read_only_mode, &ret); + if (!ret) { + return(DB_IO_ERROR); + } + + + ulint sz = UNIV_PAGE_SIZE; + void* buf = ut_zalloc_nokey(sz + UNIV_PAGE_SIZE); + if (buf == 0) { + os_file_close(handle); + return(DB_OUT_OF_MEMORY); + } + + /* Align the memory for file i/o if we might have O_DIRECT set*/ + byte* log_buf = static_cast( + ut_align(buf, UNIV_PAGE_SIZE)); + + lsn_t lsn = log_get_lsn(); + + /* Generally loop should exit in single go but + just for those 1% of rare cases we need to assume + corner case. */ + do { + /* First 4 bytes are reserved for magic number + which is currently 0. */ + err = m_truncate.write( + log_buf + 4, log_buf + sz - 4, + m_table->space, m_table->name.m_name, + m_flags, m_table->flags, lsn); + + DBUG_EXECUTE_IF("ib_err_trunc_oom_logging", + err = DB_FAIL;); + + if (err != DB_SUCCESS) { + ut_ad(err == DB_FAIL); + ut_free(buf); + sz *= 2; + buf = ut_zalloc_nokey(sz + UNIV_PAGE_SIZE); + DBUG_EXECUTE_IF("ib_err_trunc_oom_logging", + ut_free(buf); + buf = 0;); + if (buf == 0) { + os_file_close(handle); + return(DB_OUT_OF_MEMORY); + } + log_buf = static_cast( + ut_align(buf, UNIV_PAGE_SIZE)); + } + + } while (err != DB_SUCCESS); + + dberr_t io_err; + + IORequest request(IORequest::WRITE); + + io_err = os_file_write( + request, m_log_file_name, handle, log_buf, 0, sz); + + if (io_err != DB_SUCCESS) { + + ib::error() + << "IO: Failed to write the file size to '" + << m_log_file_name << "'"; + + /* Preserve the original error code */ + if (err == DB_SUCCESS) { + err = io_err; + } + } + + os_file_flush(handle); + os_file_close(handle); + + ut_free(buf); + + /* Why we need MLOG_TRUNCATE when we have truncate_log for + recovery? + - truncate log can protect us if crash happens while truncate + is active. Once truncate is done truncate log is removed. + - If crash happens post truncate and system is yet to + checkpoint, on recovery we would see REDO records from action + before truncate (unless we explicitly checkpoint before + returning from truncate API. Costly alternative so rejected). + - These REDO records may reference a page that doesn't exist + post truncate so we need a mechanism to skip all such REDO + records. MLOG_TRUNCATE records space_id and lsn that exactly + serve the purpose. + - If checkpoint happens post truncate and crash happens post + this point then neither MLOG_TRUNCATE nor REDO record + from action before truncate are accessible. */ + if (!is_system_tablespace(m_table->space)) { + mtr_t mtr; + byte* log_ptr; + + mtr_start(&mtr); + + log_ptr = mlog_open(&mtr, 11 + 8); + log_ptr = mlog_write_initial_log_record_low( + MLOG_TRUNCATE, m_table->space, 0, + log_ptr, &mtr); + + mach_write_to_8(log_ptr, lsn); + log_ptr += 8; + + mlog_close(&mtr, log_ptr); + mtr_commit(&mtr); + } + + return(err); + } + + /** + Indicate completion of truncate log by writing magic-number. + File will be removed from the system but to protect against + unlink (File-System) anomalies we ensure we write magic-number. */ + void done() + { + if (m_log_file_name == 0) { + return; + } + + bool ret; + os_file_t handle = os_file_create_simple_no_error_handling( + innodb_log_file_key, m_log_file_name, + OS_FILE_OPEN, OS_FILE_READ_WRITE, + srv_read_only_mode, &ret); + DBUG_EXECUTE_IF("ib_err_trunc_writing_magic_number", + os_file_close(handle); + ret = false;); + if (!ret) { + ib::error() << "Failed to open truncate log file " + << m_log_file_name << "." + " If server crashes before truncate log is" + " removed make sure it is manually removed" + " before restarting server"; + os_file_delete(innodb_log_file_key, m_log_file_name); + return; + } + + if (os_file_write(IORequest(IORequest::WRITE), + m_log_file_name, handle, magic, 0, + sizeof magic) != DB_SUCCESS) { + ib::error() + << "IO: Failed to write the magic number to '" + << m_log_file_name << "'"; + } + + DBUG_EXECUTE_IF("ib_trunc_crash_after_updating_magic_no", + DBUG_SUICIDE();); + os_file_flush(handle); + os_file_close(handle); + DBUG_EXECUTE_IF("ib_trunc_crash_after_logging_complete", + log_buffer_flush_to_disk(); + os_thread_sleep(1000000); + DBUG_SUICIDE();); + os_file_delete(innodb_log_file_key, m_log_file_name); + } + +private: + /** Lookup the index using the index id. + @return index instance if found else NULL */ + const dict_index_t* find(index_id_t id) const + { + for (const dict_index_t* index = UT_LIST_GET_FIRST( + m_table->indexes); + index != NULL; + index = UT_LIST_GET_NEXT(indexes, index)) { + + if (index->id == id) { + return(index); + } + } + + return(NULL); + } + +private: + /** Table to be truncated */ + dict_table_t* m_table; + + /** Tablespace flags */ + ulint m_flags; + + /** Collect table to truncate information */ + truncate_t m_truncate; + + /** Truncate log file name. */ + char* m_log_file_name; +}; + /** Scan to find out truncate log file from the given directory path. @@ -355,7 +652,7 @@ TruncateLogParser::parse( break; } - if (mach_read_from_4(log_buf) == 32743712) { + if (!memcmp(log_buf, magic, sizeof magic)) { /* Truncate action completed. Avoid parsing the file. */ os_file_close(handle); @@ -551,6 +848,58 @@ private: bool m_table_found; }; +/** +@param mtr mini-transaction covering the read +@param pcur persistent cursor used for reading +@return DB_SUCCESS or error code */ +dberr_t +TruncateLogger::operator()(mtr_t* mtr, btr_pcur_t* pcur) +{ + ulint len; + const byte* field; + rec_t* rec = btr_pcur_get_rec(pcur); + truncate_t::index_t index; + + field = rec_get_nth_field_old( + rec, DICT_FLD__SYS_INDEXES__TYPE, &len); + ut_ad(len == 4); + index.m_type = mach_read_from_4(field); + + field = rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__ID, &len); + ut_ad(len == 8); + index.m_id = mach_read_from_8(field); + + field = rec_get_nth_field_old( + rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len); + ut_ad(len == 4); + index.m_root_page_no = mach_read_from_4(field); + + /* For compressed tables we need to store extra meta-data + required during btr_create(). */ + if (FSP_FLAGS_GET_ZIP_SSIZE(m_flags)) { + + const dict_index_t* dict_index = find(index.m_id); + + if (dict_index != NULL) { + + dberr_t err = index.set(dict_index); + + if (err != DB_SUCCESS) { + m_truncate.clear(); + return(err); + } + + } else { + ib::warn() << "Index id " << index.m_id + << " not found"; + } + } + + m_truncate.add(index); + + return(DB_SUCCESS); +} + /** Drop an index in the table. @@ -736,6 +1085,251 @@ TableLocator::operator()(mtr_t* mtr, btr_pcur_t* pcur) return(DB_SUCCESS); } +/** +Rollback the transaction and release the index locks. +Drop indexes if table is corrupted so that drop/create +sequence works as expected. + +@param table table to truncate +@param trx transaction covering the TRUNCATE +@param new_id new table id that was suppose to get assigned + to the table if truncate executed successfully. +@param has_internal_doc_id indicate existence of fts index +@param no_redo if true, turn-off redo logging +@param corrupted table corrupted status +@param unlock_index if true then unlock indexes before action */ +static +void +row_truncate_rollback( + dict_table_t* table, + trx_t* trx, + table_id_t new_id, + bool has_internal_doc_id, + bool no_redo, + bool corrupted, + bool unlock_index) +{ + if (unlock_index) { + dict_table_x_unlock_indexes(table); + } + + trx->error_state = DB_SUCCESS; + + trx_rollback_to_savepoint(trx, NULL); + + trx->error_state = DB_SUCCESS; + + if (corrupted && !dict_table_is_temporary(table)) { + + /* Cleanup action to ensure we don't left over stale entries + if we are marking table as corrupted. This will ensure + it can be recovered using drop/create sequence. */ + dict_table_x_lock_indexes(table); + + DropIndex dropIndex(table, no_redo); + + SysIndexIterator().for_each(dropIndex); + + dict_table_x_unlock_indexes(table); + + for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); + index != NULL; + index = UT_LIST_GET_NEXT(indexes, index)) { + + dict_set_corrupted(index, trx, "TRUNCATE TABLE"); + } + + if (has_internal_doc_id) { + + ut_ad(!trx_is_started(trx)); + + table_id_t id = table->id; + + table->id = new_id; + + fts_drop_tables(trx, table); + + table->id = id; + + ut_ad(trx_is_started(trx)); + + trx_commit_for_mysql(trx); + } + + } else if (corrupted && dict_table_is_temporary(table)) { + + dict_table_x_lock_indexes(table); + + for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); + index != NULL; + index = UT_LIST_GET_NEXT(indexes, index)) { + + dict_drop_index_tree_in_mem(index, index->page); + + index->page = FIL_NULL; + } + + dict_table_x_unlock_indexes(table); + } + + table->corrupted = corrupted; +} + +/** +Finish the TRUNCATE operations for both commit and rollback. + +@param table table being truncated +@param trx transaction covering the truncate +@param fsp_flags tablespace flags +@param logger table to truncate information logger +@param err status of truncate operation + +@return DB_SUCCESS or error code */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_complete( + dict_table_t* table, + trx_t* trx, + ulint fsp_flags, + TruncateLogger* &logger, + dberr_t err) +{ + bool is_file_per_table = dict_table_is_file_per_table(table); + + /* Add the table back to FTS optimize background thread. */ + if (table->fts) { + fts_optimize_add_table(table); + } + + row_mysql_unlock_data_dictionary(trx); + + DEBUG_SYNC_C("ib_trunc_table_trunc_completing"); + + if (!dict_table_is_temporary(table)) { + + DBUG_EXECUTE_IF("ib_trunc_crash_before_log_removal", + log_buffer_flush_to_disk(); + os_thread_sleep(500000); + DBUG_SUICIDE();); + + /* Note: We don't log-checkpoint instead we have written + a special REDO log record MLOG_TRUNCATE that is used to + avoid applying REDO records before truncate for crash + that happens post successful truncate completion. */ + + if (logger != NULL) { + logger->done(); + UT_DELETE(logger); + logger = NULL; + } + } + + /* If non-temp file-per-table tablespace... */ + if (is_file_per_table + && !dict_table_is_temporary(table) + && fsp_flags != ULINT_UNDEFINED) { + + /* This function will reset back the stop_new_ops + and is_being_truncated so that fil-ops can re-start. */ + dberr_t err2 = truncate_t::truncate( + table->space, + table->data_dir_path, + table->name.m_name, fsp_flags, false); + + if (err2 != DB_SUCCESS) { + return(err2); + } + } + + if (err == DB_SUCCESS) { + dict_stats_update(table, DICT_STATS_EMPTY_TABLE); + } + + trx->op_info = ""; + + /* For temporary tables or if there was an error, we need to reset + the dict operation flags. */ + trx->ddl = false; + trx->dict_operation = TRX_DICT_OP_NONE; + + ut_ad(!trx_is_started(trx)); + + srv_wake_master_thread(); + + DBUG_EXECUTE_IF("ib_trunc_crash_after_truncate_done", + DBUG_SUICIDE();); + + return(err); +} + +/** +Handle FTS truncate issues. +@param table table being truncated +@param new_id new id for the table +@param trx transaction covering the truncate +@return DB_SUCCESS or error code. */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_fts( + dict_table_t* table, + table_id_t new_id, + trx_t* trx) +{ + dict_table_t fts_table; + + fts_table.id = new_id; + fts_table.name = table->name; + fts_table.flags2 = table->flags2; + fts_table.flags = table->flags; + fts_table.space = table->space; + + /* table->data_dir_path is used for FTS AUX table + creation. */ + if (DICT_TF_HAS_DATA_DIR(table->flags) + && table->data_dir_path == NULL) { + dict_get_and_save_data_dir_path(table, true); + ut_ad(table->data_dir_path != NULL); + } + + fts_table.data_dir_path = table->data_dir_path; + + dberr_t err; + + err = fts_create_common_tables( + trx, &fts_table, table->name.m_name, TRUE); + + for (ulint i = 0; + i < ib_vector_size(table->fts->indexes) && err == DB_SUCCESS; + i++) { + + dict_index_t* fts_index; + + fts_index = static_cast( + ib_vector_getp(table->fts->indexes, i)); + + err = fts_create_index_tables_low( + trx, fts_index, table->name.m_name, new_id); + } + + DBUG_EXECUTE_IF("ib_err_trunc_during_fts_trunc", + err = DB_ERROR;); + + if (err != DB_SUCCESS) { + + trx->error_state = DB_SUCCESS; + trx_rollback_to_savepoint(trx, NULL); + trx->error_state = DB_SUCCESS; + + ib::error() << "Unable to truncate FTS index for table " + << table->name; + } else { + + ut_ad(trx_is_started(trx)); + } + + return(err); +} + /** Update system table to reflect new table id. @param old_table_id old table id @@ -876,6 +1470,626 @@ row_truncate_update_sys_tables_during_fix_up( return(err); } +/** +Truncate also results in assignment of new table id, update the system +SYSTEM TABLES with the new id. +@param table, table being truncated +@param new_id, new table id +@param has_internal_doc_id, has doc col (fts) +@param no_redo if true, turn-off redo logging +@param trx transaction handle +@return error code or DB_SUCCESS */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_update_system_tables( + dict_table_t* table, + table_id_t new_id, + bool has_internal_doc_id, + bool no_redo, + trx_t* trx) +{ + dberr_t err = DB_SUCCESS; + + ut_a(!dict_table_is_temporary(table)); + + err = row_truncate_update_table_id(table->id, new_id, FALSE, trx); + + DBUG_EXECUTE_IF("ib_err_trunc_during_sys_table_update", + err = DB_ERROR;); + + if (err != DB_SUCCESS) { + + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, true, false); + + ib::error() << "Unable to assign a new identifier to table " + << table->name << " after truncating it. Marked the" + " table as corrupted. In-memory representation is now" + " different from the on-disk representation."; + err = DB_ERROR; + } else { + /* Drop the old FTS index */ + if (has_internal_doc_id) { + + ut_ad(trx_is_started(trx)); + + fts_drop_tables(trx, table); + + DBUG_EXECUTE_IF("ib_truncate_crash_while_fts_cleanup", + DBUG_SUICIDE();); + + ut_ad(trx_is_started(trx)); + } + + DBUG_EXECUTE_IF("ib_trunc_crash_after_fts_drop", + log_buffer_flush_to_disk(); + os_thread_sleep(2000000); + DBUG_SUICIDE();); + + dict_table_change_id_in_cache(table, new_id); + + /* Reset the Doc ID in cache to 0 */ + if (has_internal_doc_id && table->fts->cache != NULL) { + DBUG_EXECUTE_IF("ib_trunc_sleep_before_fts_cache_clear", + os_thread_sleep(10000000);); + + table->fts->fts_status |= TABLE_DICT_LOCKED; + fts_update_next_doc_id(trx, table, NULL, 0); + fts_cache_clear(table->fts->cache); + fts_cache_init(table->fts->cache); + table->fts->fts_status &= uint(~TABLE_DICT_LOCKED); + } + } + + return(err); +} + +/** +Prepare for the truncate process. On success all of the table's indexes will +be locked in X mode. +@param table table to truncate +@param flags tablespace flags +@return error code or DB_SUCCESS */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_prepare(dict_table_t* table, ulint* flags) +{ + ut_ad(!dict_table_is_temporary(table)); + ut_ad(dict_table_is_file_per_table(table)); + + *flags = fil_space_get_flags(table->space); + + ut_ad(!dict_table_is_temporary(table)); + + dict_get_and_save_data_dir_path(table, true); + + if (*flags != ULINT_UNDEFINED) { + + dberr_t err = fil_prepare_for_truncate(table->space); + + if (err != DB_SUCCESS) { + return(err); + } + } + + return(DB_SUCCESS); +} + +/** +Do foreign key checks before starting TRUNCATE. +@param table table being truncated +@param trx transaction covering the truncate +@return DB_SUCCESS or error code */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_foreign_key_checks( + const dict_table_t* table, + const trx_t* trx) +{ + /* Check if the table is referenced by foreign key constraints from + some other table (not the table itself) */ + + dict_foreign_set::iterator it + = std::find_if(table->referenced_set.begin(), + table->referenced_set.end(), + dict_foreign_different_tables()); + + if (!srv_read_only_mode + && it != table->referenced_set.end() + && trx->check_foreigns) { + + dict_foreign_t* foreign = *it; + + FILE* ef = dict_foreign_err_file; + + /* We only allow truncating a referenced table if + FOREIGN_KEY_CHECKS is set to 0 */ + + mutex_enter(&dict_foreign_err_mutex); + + rewind(ef); + + ut_print_timestamp(ef); + + fputs(" Cannot truncate table ", ef); + ut_print_name(ef, trx, table->name.m_name); + fputs(" by DROP+CREATE\n" + "InnoDB: because it is referenced by ", ef); + ut_print_name(ef, trx, foreign->foreign_table_name); + putc('\n', ef); + + mutex_exit(&dict_foreign_err_mutex); + + return(DB_ERROR); + } + + /* TODO: could we replace the counter n_foreign_key_checks_running + with lock checks on the table? Acquire here an exclusive lock on the + table, and rewrite lock0lock.cc and the lock wait in srv0srv.cc so that + they can cope with the table having been truncated here? Foreign key + checks take an IS or IX lock on the table. */ + + if (table->n_foreign_key_checks_running > 0) { + ib::warn() << "Cannot truncate table " << table->name + << " because there is a foreign key check running on" + " it."; + + return(DB_ERROR); + } + + return(DB_SUCCESS); +} + +/** +Do some sanity checks before starting the actual TRUNCATE. +@param table table being truncated +@return DB_SUCCESS or error code */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_sanity_checks( + const dict_table_t* table) +{ + if (dict_table_is_discarded(table)) { + + return(DB_TABLESPACE_DELETED); + + } else if (!table->is_readable()) { + if (fil_space_get(table->space) == NULL) { + return(DB_TABLESPACE_NOT_FOUND); + + } else { + return(DB_DECRYPTION_FAILED); + } + } else if (dict_table_is_corrupted(table)) { + + return(DB_TABLE_CORRUPT); + } + + return(DB_SUCCESS); +} + +/** +Truncates a table for MySQL. +@param table table being truncated +@param trx transaction covering the truncate +@return error code or DB_SUCCESS */ +dberr_t row_truncate_table_for_mysql(dict_table_t* table, trx_t* trx) +{ + bool is_file_per_table = dict_table_is_file_per_table(table); + dberr_t err; +#ifdef UNIV_DEBUG + ulint old_space = table->space; +#endif /* UNIV_DEBUG */ + TruncateLogger* logger = NULL; + + /* Understanding the truncate flow. + + Step-1: Perform intiial sanity check to ensure table can be truncated. + This would include check for tablespace discard status, ibd file + missing, etc .... + + Step-2: Start transaction (only for non-temp table as temp-table don't + modify any data on disk doesn't need transaction object). + + Step-3: Validate ownership of needed locks (Exclusive lock). + Ownership will also ensure there is no active SQL queries, INSERT, + SELECT, ..... + + Step-4: Stop all the background process associated with table. + + Step-5: There are few foreign key related constraint under which + we can't truncate table (due to referential integrity unless it is + turned off). Ensure this condition is satisfied. + + Step-6: Truncate operation can be rolled back in case of error + till some point. Associate rollback segment to record undo log. + + Step-7: Generate new table-id. + Why we need new table-id ? + Purge and rollback case: we assign a new table id for the table. + Since purge and rollback look for the table based on the table id, + they see the table as 'dropped' and discard their operations. + + Step-8: Log information about tablespace which includes + table and index information. If there is a crash in the next step + then during recovery we will attempt to fixup the operation. + + Step-9: Drop all indexes (this include freeing of the pages + associated with them). + + Step-10: Re-create new indexes. + + Step-11: Update new table-id to in-memory cache (dictionary), + on-disk (INNODB_SYS_TABLES). INNODB_SYS_INDEXES also needs to + be updated to reflect updated root-page-no of new index created + and updated table-id. + + Step-12: Cleanup Stage. Reset auto-inc value to 1. + Release all the locks. + Commit the transaction. Update trx operation state. + + Notes: + - On error, log checkpoint is done followed writing of magic number to + truncate log file. If servers crashes after truncate, fix-up action + will not be applied. + + - log checkpoint is done before starting truncate table to ensure + that previous REDO log entries are not applied if current truncate + crashes. Consider following use-case: + - create table .... insert/load table .... truncate table (crash) + - on restart table is restored .... truncate table (crash) + - on restart (assuming default log checkpoint is not done) will have + 2 REDO log entries for same table. (Note 2 REDO log entries + for different table is not an issue). + For system-tablespace we can't truncate the tablespace so we need + to initiate a local cleanup that involves dropping of indexes and + re-creating them. If we apply stale entry we might end-up issuing + drop on wrong indexes. + + - Insert buffer: TRUNCATE TABLE is analogous to DROP TABLE, + so we do not have to remove insert buffer records, as the + insert buffer works at a low level. If a freed page is later + reallocated, the allocator will remove the ibuf entries for + it. When we prepare to truncate *.ibd files, we remove all entries + for the table in the insert buffer tree. This is not strictly + necessary, but we can free up some space in the system tablespace. + + - Linear readahead and random readahead: we use the same + method as in 3) to discard ongoing operations. (This is only + relevant for TRUNCATE TABLE by TRUNCATE TABLESPACE.) + Ensure that the table will be dropped by trx_rollback_active() in + case of a crash. + */ + + /*-----------------------------------------------------------------*/ + /* Step-1: Perform intiial sanity check to ensure table can be + truncated. This would include check for tablespace discard status, + ibd file missing, etc .... */ + err = row_truncate_sanity_checks(table); + if (err != DB_SUCCESS) { + return(err); + + } + + /* Step-2: Start transaction (only for non-temp table as temp-table + don't modify any data on disk doesn't need transaction object). */ + if (!dict_table_is_temporary(table)) { + if (table->fts) { + fts_optimize_remove_table(table); + } + + /* Avoid transaction overhead for temporary table DDL. */ + trx_start_for_ddl(trx, TRX_DICT_OP_TABLE); + } + + DEBUG_SYNC_C("row_trunc_before_dict_lock"); + + /* Step-3: Validate ownership of needed locks (Exclusive lock). + Ownership will also ensure there is no active SQL queries, INSERT, + SELECT, .....*/ + trx->op_info = "truncating table"; + ut_a(trx->dict_operation_lock_mode == 0); + row_mysql_lock_data_dictionary(trx); + ut_ad(mutex_own(&dict_sys->mutex)); + ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X)); + + /* Step-4: Stop all the background process associated with table. */ + dict_stats_wait_bg_to_stop_using_table(table, trx); + + /* Step-5: There are few foreign key related constraint under which + we can't truncate table (due to referential integrity unless it is + turned off). Ensure this condition is satisfied. */ + ulint fsp_flags = ULINT_UNDEFINED; + err = row_truncate_foreign_key_checks(table, trx); + if (err != DB_SUCCESS) { + trx_rollback_to_savepoint(trx, NULL); + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + + /* Remove all locks except the table-level X lock. */ + lock_remove_all_on_table(table, FALSE); + trx->table_id = table->id; + trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); + + /* Step-6: Truncate operation can be rolled back in case of error + till some point. Associate rollback segment to record undo log. */ + if (!dict_table_is_temporary(table)) { + mutex_enter(&trx->undo_mutex); + + trx_undo_t** pundo = &trx->rsegs.m_redo.update_undo; + err = trx_undo_assign_undo( + trx, trx->rsegs.m_redo.rseg, pundo, TRX_UNDO_UPDATE); + + mutex_exit(&trx->undo_mutex); + + DBUG_EXECUTE_IF("ib_err_trunc_assigning_undo_log", + err = DB_ERROR;); + if (err != DB_SUCCESS) { + trx_rollback_to_savepoint(trx, NULL); + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } + + /* Step-7: Generate new table-id. + Why we need new table-id ? + Purge and rollback: we assign a new table id for the + table. Since purge and rollback look for the table based on + the table id, they see the table as 'dropped' and discard + their operations. */ + table_id_t new_id; + dict_hdr_get_new_id(&new_id, NULL, NULL, table, false); + + /* Check if table involves FTS index. */ + bool has_internal_doc_id = + dict_table_has_fts_index(table) + || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID); + + bool no_redo = is_file_per_table && !has_internal_doc_id; + + /* Step-8: Log information about tablespace which includes + table and index information. If there is a crash in the next step + then during recovery we will attempt to fixup the operation. */ + + /* Lock all index trees for this table, as we will truncate + the table/index and possibly change their metadata. All + DML/DDL are blocked by table level X lock, with a few exceptions + such as queries into information schema about the table, + MySQL could try to access index stats for this kind of query, + we need to use index locks to sync up */ + dict_table_x_lock_indexes(table); + + if (!dict_table_is_temporary(table)) { + + if (is_file_per_table) { + + err = row_truncate_prepare(table, &fsp_flags); + + DBUG_EXECUTE_IF("ib_err_trunc_preparing_for_truncate", + err = DB_ERROR;); + + if (err != DB_SUCCESS) { + row_truncate_rollback( + table, trx, new_id, + has_internal_doc_id, + no_redo, false, true); + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } else { + fsp_flags = fil_space_get_flags(table->space); + + DBUG_EXECUTE_IF("ib_err_trunc_preparing_for_truncate", + fsp_flags = ULINT_UNDEFINED;); + + if (fsp_flags == ULINT_UNDEFINED) { + row_truncate_rollback( + table, trx, new_id, + has_internal_doc_id, + no_redo, false, true); + return(row_truncate_complete( + table, trx, fsp_flags, + logger, DB_ERROR)); + } + } + + logger = UT_NEW_NOKEY(TruncateLogger( + table, fsp_flags, new_id)); + + err = logger->init(); + if (err != DB_SUCCESS) { + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, false, true); + return(row_truncate_complete( + table, trx, fsp_flags, logger, DB_ERROR)); + + } + + err = SysIndexIterator().for_each(*logger); + if (err != DB_SUCCESS) { + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, false, true); + return(row_truncate_complete( + table, trx, fsp_flags, logger, DB_ERROR)); + + } + + ut_ad(logger->debug()); + + err = logger->log(); + + if (err != DB_SUCCESS) { + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, false, true); + return(row_truncate_complete( + table, trx, fsp_flags, logger, DB_ERROR)); + } + } + + DBUG_EXECUTE_IF("ib_trunc_crash_after_redo_log_write_complete", + log_buffer_flush_to_disk(); + os_thread_sleep(3000000); + DBUG_SUICIDE();); + + /* Step-9: Drop all indexes (free index pages associated with these + indexes) */ + if (!dict_table_is_temporary(table)) { + + DropIndex dropIndex(table, no_redo); + + err = SysIndexIterator().for_each(dropIndex); + + if (err != DB_SUCCESS) { + + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, true, true); + + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } else { + /* For temporary tables we don't have entries in SYSTEM TABLES*/ + ut_ad(fsp_is_system_temporary(table->space)); + for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); + index != NULL; + index = UT_LIST_GET_NEXT(indexes, index)) { + + err = dict_truncate_index_tree_in_mem(index); + + if (err != DB_SUCCESS) { + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, true, true); + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + + DBUG_EXECUTE_IF( + "ib_trunc_crash_during_drop_index_temp_table", + log_buffer_flush_to_disk(); + os_thread_sleep(2000000); + DBUG_SUICIDE();); + } + } + + if (is_file_per_table && fsp_flags != ULINT_UNDEFINED) { + /* A single-table tablespace has initially + FIL_IBD_FILE_INITIAL_SIZE number of pages allocated and an + extra page is allocated for each of the indexes present. But in + the case of clust index 2 pages are allocated and as one is + covered in the calculation as part of table->indexes.count we + take care of the other page by adding 1. */ + ulint space_size = table->indexes.count + + FIL_IBD_FILE_INITIAL_SIZE + 1; + + if (has_internal_doc_id) { + /* Since aux tables are created for fts indexes and + they use seperate tablespaces. */ + space_size -= ib_vector_size(table->fts->indexes); + } + + fil_reinit_space_header_for_table(table, space_size, trx); + } + + DBUG_EXECUTE_IF("ib_trunc_crash_with_intermediate_log_checkpoint", + log_buffer_flush_to_disk(); + os_thread_sleep(2000000); + log_checkpoint(TRUE, TRUE); + os_thread_sleep(1000000); + DBUG_SUICIDE();); + + DBUG_EXECUTE_IF("ib_trunc_crash_drop_reinit_done_create_to_start", + log_buffer_flush_to_disk(); + os_thread_sleep(2000000); + DBUG_SUICIDE();); + + /* Step-10: Re-create new indexes. */ + if (!dict_table_is_temporary(table)) { + + CreateIndex createIndex(table, no_redo); + + err = SysIndexIterator().for_each(createIndex); + + if (err != DB_SUCCESS) { + + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, true, true); + + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } + + /* Done with index truncation, release index tree locks, + subsequent work relates to table level metadata change */ + dict_table_x_unlock_indexes(table); + + if (has_internal_doc_id) { + + err = row_truncate_fts(table, new_id, trx); + + if (err != DB_SUCCESS) { + + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, true, false); + + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } + + /* Step-11: Update new table-id to in-memory cache (dictionary), + on-disk (INNODB_SYS_TABLES). INNODB_SYS_INDEXES also needs to + be updated to reflect updated root-page-no of new index created + and updated table-id. */ + if (dict_table_is_temporary(table)) { + + dict_table_change_id_in_cache(table, new_id); + err = DB_SUCCESS; + + } else { + + /* If this fails then we are in an inconsistent state and + the results are undefined. */ + ut_ad(old_space == table->space); + + err = row_truncate_update_system_tables( + table, new_id, has_internal_doc_id, no_redo, trx); + + if (err != DB_SUCCESS) { + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } + + DBUG_EXECUTE_IF("ib_trunc_crash_on_updating_dict_sys_info", + log_buffer_flush_to_disk(); + os_thread_sleep(2000000); + DBUG_SUICIDE();); + + /* Step-12: Cleanup Stage. Reset auto-inc value to 1. + Release all the locks. + Commit the transaction. Update trx operation state. */ + dict_table_autoinc_lock(table); + dict_table_autoinc_initialize(table, 1); + dict_table_autoinc_unlock(table); + + if (trx_is_started(trx)) { + + trx_commit_for_mysql(trx); + } + + return(row_truncate_complete(table, trx, fsp_flags, logger, err)); +} + /** Fix the table truncate by applying information parsed from TRUNCATE log. Fix-up includes re-creating table (drop and re-create indexes) diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 342f0d222e0..171e06894ca 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -286,6 +286,34 @@ row_upd_check_references_constraints( FALSE, FALSE, DICT_ERR_IGNORE_NONE); } + /* dict_operation_lock is held both here + (UPDATE or DELETE with FOREIGN KEY) and by TRUNCATE + TABLE operations. + If a TRUNCATE TABLE operation is in progress, + there can be 2 possible conditions: + 1) row_truncate_table_for_mysql() is not yet called. + 2) Truncate releases dict_operation_lock + during eviction of pages from buffer pool + for a file-per-table tablespace. + + In case of (1), truncate will wait for FK operation + to complete. + In case of (2), truncate will be rolled forward even + if it is interrupted. So if the foreign table is + undergoing a truncate, ignore the FK check. */ + + if (foreign_table) { + mutex_enter(&fil_system->mutex); + const fil_space_t* space = fil_space_get_by_id( + foreign_table->space); + const bool being_truncated = space + && space->is_being_truncated; + mutex_exit(&fil_system->mutex); + if (being_truncated) { + continue; + } + } + /* NOTE that if the thread ends up waiting for a lock we will release dict_operation_lock temporarily! But the counter on the table protects 'foreign' from diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 7ebe0015ffe..10bd308ec53 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -152,6 +152,9 @@ my_bool srv_read_only_mode; /** store to its own file each table created by an user; data dictionary tables are in the system tablespace 0 */ my_bool srv_file_per_table; +/** whether to use the MySQL 5.7 WL#6501 TRUNCATE TABLE implementation +that does not work with backup */ +my_bool srv_57_truncate; /** The file format to use on new *.ibd files. */ ulint srv_file_format; /** Whether to check file format during startup. A value of diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index ca0e1472aed..c39a5ea1937 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1393,10 +1393,17 @@ srv_prepare_to_delete_redo_log_files( ulint pending_io = 0; ulint count = 0; - if ((log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) - != LOG_HEADER_FORMAT_CURRENT - || log_sys->log.subformat != 1) { - srv_log_file_size = 0; + if (srv_57_truncate) { + if ((log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) + != LOG_HEADER_FORMAT_10_2) { + srv_log_file_size = 0; + } + } else { + if ((log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) + != LOG_HEADER_FORMAT_10_3 + || log_sys->log.subformat != 1) { + srv_log_file_size = 0; + } } do { @@ -1417,7 +1424,7 @@ srv_prepare_to_delete_redo_log_files( if (srv_log_file_size == 0) { info << ((log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) - < LOG_HEADER_FORMAT_CURRENT + < LOG_HEADER_FORMAT_10_3 ? "Upgrading redo log: " : "Downgrading redo log: "); } else if (n_files != srv_n_log_files @@ -2392,11 +2399,16 @@ files_checked: } else if (srv_log_file_size_requested == srv_log_file_size && srv_n_log_files_found == srv_n_log_files && log_sys->log.format - == (srv_encrypt_log - ? LOG_HEADER_FORMAT_CURRENT - | LOG_HEADER_FORMAT_ENCRYPTED - : LOG_HEADER_FORMAT_CURRENT) - && log_sys->log.subformat == 1) { + == (srv_57_truncate + ? (srv_encrypt_log + ? LOG_HEADER_FORMAT_10_2 + | LOG_HEADER_FORMAT_ENCRYPTED + : LOG_HEADER_FORMAT_10_2) + : (srv_encrypt_log + ? LOG_HEADER_FORMAT_10_3 + | LOG_HEADER_FORMAT_ENCRYPTED + : LOG_HEADER_FORMAT_10_3)) + && log_sys->log.subformat == !srv_57_truncate) { /* No need to add or remove encryption, upgrade, downgrade, or resize. */ } else { diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 1c55106f016..a50cdbaad6f 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1938,6 +1938,7 @@ trx_undo_report_rename(trx_t* trx, const dict_table_t* table) ut_ad(!trx->read_only); ut_ad(trx->id); ut_ad(!table->is_temporary()); + ut_ad(!srv_57_truncate); trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; trx_undo_t** pundo = &trx->rsegs.m_redo.insert_undo;