summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-10-10 19:19:29 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-10-11 08:17:04 +0300
commit3448ceb02a00f4784d41e3074fb3508d8a79ae48 (patch)
tree2e1bc12961a13bd969c1877f052829fdd9ab1a03
parent07815d9555b099482f8877ec700bbc39d1d553dd (diff)
downloadmariadb-git-3448ceb02a00f4784d41e3074fb3508d8a79ae48.tar.gz
MDEV-13564: Implement innodb_unsafe_truncate=ON for compatibility
While MariaDB Server 10.2 is not really guaranteed to be compatible with Percona XtraBackup 2.4 (for example, the MySQL 5.7 undo log format change that could be present in XtraBackup, but was reverted from MariaDB in MDEV-12289), we do not want to disrupt users who have deployed xtrabackup and MariaDB Server 10.2 in their environments. With this change, MariaDB 10.2 will continue to use the backup-unsafe TRUNCATE TABLE code, so that neither the undo log nor the redo log formats will change in an incompatible way. Undo tablespace truncation will keep using the redo log only. Recovery or backup with old code will fail to shrink the undo tablespace files, but the contents will be recovered just fine. In the MariaDB Server 10.2 series only, we introduce the configuration parameter innodb_unsafe_truncate and make it ON by default. To allow MariaDB Backup (mariabackup) to work properly with TRUNCATE TABLE operations, use loose_innodb_unsafe_truncate=OFF. MariaDB Server 10.3.10 and later releases will always use the backup-safe TRUNCATE TABLE, and this parameter will not be added there. recv_recovery_rollback_active(): Skip row_mysql_drop_garbage_tables() unless innodb_unsafe_truncate=OFF. It is too unsafe to drop orphan tables if RENAME operations are not transactional within InnoDB. LOG_HEADER_FORMAT_10_3: Replaces LOG_HEADER_FORMAT_CURRENT. log_init(), log_group_file_header_flush(), srv_prepare_to_delete_redo_log_files(), innobase_start_or_create_for_mysql(): Choose the redo log format and subformat based on the value of innodb_unsafe_truncate.
-rw-r--r--mysql-test/suite/gcol/t/innodb_virtual_debug_purge.opt1
-rw-r--r--mysql-test/suite/innodb/include/innodb_wl6501_crash.inc416
-rw-r--r--mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc98
-rw-r--r--mysql-test/suite/innodb/include/truncate_recover.inc8
-rw-r--r--mysql-test/suite/innodb/r/truncate_debug.result88
-rw-r--r--mysql-test/suite/innodb/r/truncate_inject.result114
-rw-r--r--mysql-test/suite/innodb/r/truncate_purge_debug.result29
-rw-r--r--mysql-test/suite/innodb/r/truncate_restart.result12
-rw-r--r--mysql-test/suite/innodb/t/alter_copy.opt1
-rw-r--r--mysql-test/suite/innodb/t/alter_crash.opt1
-rw-r--r--mysql-test/suite/innodb/t/drop_table_background.opt1
-rw-r--r--mysql-test/suite/innodb/t/rename_table_debug.opt1
-rw-r--r--mysql-test/suite/innodb/t/truncate.opt1
-rw-r--r--mysql-test/suite/innodb/t/truncate_crash.opt1
-rw-r--r--mysql-test/suite/innodb/t/truncate_debug.test127
-rw-r--r--mysql-test/suite/innodb/t/truncate_foreign.opt1
-rw-r--r--mysql-test/suite/innodb/t/truncate_inject.test97
-rw-r--r--mysql-test/suite/innodb/t/truncate_missing.opt1
-rw-r--r--mysql-test/suite/innodb/t/truncate_purge_debug.opt3
-rw-r--r--mysql-test/suite/innodb/t/truncate_purge_debug.test49
-rw-r--r--mysql-test/suite/innodb/t/truncate_restart.test16
-rw-r--r--mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc112
-rw-r--r--mysql-test/suite/innodb_zip/r/wl6501_1.result1202
-rw-r--r--mysql-test/suite/innodb_zip/r/wl6501_crash_3.result462
-rw-r--r--mysql-test/suite/innodb_zip/r/wl6501_crash_4.result519
-rw-r--r--mysql-test/suite/innodb_zip/r/wl6501_crash_5.result462
-rw-r--r--mysql-test/suite/innodb_zip/r/wl6501_scale_1.result345
-rw-r--r--mysql-test/suite/innodb_zip/t/restart.opt1
-rw-r--r--mysql-test/suite/innodb_zip/t/wl6501_1.test451
-rw-r--r--mysql-test/suite/innodb_zip/t/wl6501_crash_3.test25
-rw-r--r--mysql-test/suite/innodb_zip/t/wl6501_crash_4.test27
-rw-r--r--mysql-test/suite/innodb_zip/t/wl6501_crash_5.test25
-rw-r--r--mysql-test/suite/innodb_zip/t/wl6501_scale_1.test37
-rw-r--r--mysql-test/suite/mariabackup/truncate_during_backup.opt1
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb.result14
-rw-r--r--storage/innobase/dict/dict0crea.cc67
-rw-r--r--storage/innobase/fil/fil0fil.cc150
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc1
-rw-r--r--storage/innobase/handler/ha_innodb.cc37
-rw-r--r--storage/innobase/include/dict0crea.h8
-rw-r--r--storage/innobase/include/fil0fil.h31
-rw-r--r--storage/innobase/include/log0log.h4
-rw-r--r--storage/innobase/include/row0trunc.h5
-rw-r--r--storage/innobase/include/srv0srv.h3
-rw-r--r--storage/innobase/log/log0log.cc20
-rw-r--r--storage/innobase/log/log0recv.cc13
-rw-r--r--storage/innobase/row/row0ins.cc3
-rw-r--r--storage/innobase/row/row0mysql.cc2
-rw-r--r--storage/innobase/row/row0trunc.cc1216
-rw-r--r--storage/innobase/row/row0upd.cc28
-rw-r--r--storage/innobase/srv/srv0srv.cc3
-rw-r--r--storage/innobase/srv/srv0start.cc32
-rw-r--r--storage/innobase/trx/trx0rec.cc1
53 files changed, 6346 insertions, 27 deletions
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
@@ -143,6 +143,14 @@ dict_create_index_tree_in_mem(
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
dict_drop_index_tree_in_mem(
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<char*>(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 {
@@ -241,6 +243,301 @@ protected:
};
/**
+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<byte*>(
+ 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<byte*>(
+ 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.
@param dir_path look for log directory in following 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);
@@ -552,6 +849,58 @@ private:
};
/**
+@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.
@param mtr mini-transaction covering the read
@@ -737,6 +1086,251 @@ TableLocator::operator()(mtr_t* mtr, btr_pcur_t* pcur)
}
/**
+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<dict_index_t*>(
+ 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
@param new_table_id new table id
@@ -877,6 +1471,626 @@ row_truncate_update_sys_tables_during_fix_up(
}
/**
+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)
@return error code or DB_SUCCESS */
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;