From c62e49d0cf90c1631e78ae3b10f2cb9383ac2d27 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Mon, 1 Oct 2018 09:53:37 +0200 Subject: MDEV-16656: DROP DATABASE crashes the Galera Cluster When converting table identifiers to a new format, some tables can be renamed twice, which subsequently leads to the appearance of "false" auxiliary tables belonging to another main (parent) table (which does not actually have auxiliary tables). This is because the table number is repeatedly added to the aux_tables_to_rename vector inside the function fts_check_and_drop_orphaned_tables. To correct this error, we must add a check for the occurrence of the table number in the aux_tables_to_rename vector before adding a new element. https://jira.mariadb.org/browse/MDEV-16656 --- .../suite/galera/r/galera_drop_database.result | 17 ++++++ .../suite/galera/t/galera_drop_database.test | 65 ++++++++++++++++++++++ storage/innobase/fts/fts0fts.cc | 25 ++++++++- storage/xtradb/fts/fts0fts.cc | 25 ++++++++- 4 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_drop_database.result create mode 100644 mysql-test/suite/galera/t/galera_drop_database.test diff --git a/mysql-test/suite/galera/r/galera_drop_database.result b/mysql-test/suite/galera/r/galera_drop_database.result new file mode 100644 index 00000000000..79789da5a11 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_drop_database.result @@ -0,0 +1,17 @@ +CREATE DATABASE fts; +USE fts; +CREATE TABLE fts_t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB; +CREATE TABLE fts_t2 (f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB; +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +INSERT INTO fts_t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3; +INSERT INTO fts_t2 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3; +DROP TABLE ten; +UPDATE fts_t1 SET f2 = 'abcd'; +UPDATE fts_t2 SET f2 = 'efjh'; +USE fts; +DROP TABLE fts_t1; +DROP TABLE fts_t2; +SHOW TABLES; +Tables_in_fts +DROP DATABASE fts; diff --git a/mysql-test/suite/galera/t/galera_drop_database.test b/mysql-test/suite/galera/t/galera_drop_database.test new file mode 100644 index 00000000000..47fe8315198 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_drop_database.test @@ -0,0 +1,65 @@ +# +# This test tests a DROP empty database +# +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +CREATE DATABASE fts; +USE fts; +CREATE TABLE fts_t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB; +CREATE TABLE fts_t2 (f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB; + +# Insert 1K rows +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +INSERT INTO fts_t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3; +INSERT INTO fts_t2 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3; +DROP TABLE ten; +UPDATE fts_t1 SET f2 = 'abcd'; +UPDATE fts_t2 SET f2 = 'efjh'; + +--connection node_2 +let $wsrep_cluster_address = `SELECT @@global.wsrep_node_incoming_address`; +--source include/restart_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a +--source include/wait_until_ready.inc + +--connection node_1 +--let $restart_parameters = --wsrep-cluster-address=gcomm://$wsrep_cluster_address +--source include/restart_mysqld.inc + +--connection node_2a +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--let $galera_connection_name = node_1a +--let $galera_server_number = 1 +--source include/galera_connect.inc +--connection node_1a +--source include/wait_until_ready.inc + +USE fts; +DROP TABLE fts_t1; +DROP TABLE fts_t2; +SHOW TABLES; +DROP DATABASE fts; + +# Restore original auto_increment_offset values. +--let $node_1=node_1a +--let $node_2=node_2a +--source include/auto_increment_offset_restore.inc + +--source include/galera_end.inc diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index a5b2bbb47ce..04aaff96b91 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -2762,7 +2762,7 @@ retry: mutex_enter(&cache->doc_id_lock); /* For each sync operation, we will add next_doc_id by 1, so to mark a sync operation */ - if (cache->next_doc_id < cache->synced_doc_id + 1) { + if (cache->next_doc_id <= cache->synced_doc_id) { cache->next_doc_id = cache->synced_doc_id + 1; } mutex_exit(&cache->doc_id_lock); @@ -6665,7 +6665,6 @@ fts_rename_aux_tables_to_hex_format( "All the fts index associated with the table are " "marked as corrupted. Please rebuild the " "index again.", parent_table->name); - fts_sql_rollback(trx_rename); /* Corrupting the fts index related to parent table. */ trx_t* trx_corrupt; @@ -7042,7 +7041,27 @@ fts_check_and_drop_orphaned_tables( /* If the aux table is in decimal format, we should rename it, so push it to aux_tables_to_rename */ if (!drop && rename) { - ib_vector_push(aux_tables_to_rename, aux_table); + /* It is necessary to check that the table with + this name is missing in the vector - otherwise it + can be renamed twice: */ + bool rename_table = true; + for (ulint count = 0; + count < ib_vector_size(aux_tables_to_rename); + count++) { + fts_aux_table_t* rename_aux = + static_cast( + ib_vector_get(aux_tables_to_rename, + count)); + if (strcmp(rename_aux->name, + aux_table->name) == 0) { + rename_table = false; + break; + } + } + if (rename_table) { + ib_vector_push(aux_tables_to_rename, + aux_table); + } } if (i + 1 < ib_vector_size(tables)) { diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index 5981c24c470..d5128955f56 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/fts/fts0fts.cc @@ -2761,7 +2761,7 @@ retry: mutex_enter(&cache->doc_id_lock); /* For each sync operation, we will add next_doc_id by 1, so to mark a sync operation */ - if (cache->next_doc_id < cache->synced_doc_id + 1) { + if (cache->next_doc_id <= cache->synced_doc_id) { cache->next_doc_id = cache->synced_doc_id + 1; } mutex_exit(&cache->doc_id_lock); @@ -6664,7 +6664,6 @@ fts_rename_aux_tables_to_hex_format( "All the fts index associated with the table are " "marked as corrupted. Please rebuild the " "index again.", parent_table->name); - fts_sql_rollback(trx_rename); /* Corrupting the fts index related to parent table. */ trx_t* trx_corrupt; @@ -7041,7 +7040,27 @@ fts_check_and_drop_orphaned_tables( /* If the aux table is in decimal format, we should rename it, so push it to aux_tables_to_rename */ if (!drop && rename) { - ib_vector_push(aux_tables_to_rename, aux_table); + /* It is necessary to check that the table with + this name is missing in the vector - otherwise it + can be renamed twice: */ + bool rename_table = true; + for (ulint count = 0; + count < ib_vector_size(aux_tables_to_rename); + count++) { + fts_aux_table_t* rename_aux = + static_cast( + ib_vector_get(aux_tables_to_rename, + count)); + if (strcmp(rename_aux->name, + aux_table->name) == 0) { + rename_table = false; + break; + } + } + if (rename_table) { + ib_vector_push(aux_tables_to_rename, + aux_table); + } } if (i + 1 < ib_vector_size(tables)) { -- cgit v1.2.1 From 865237e5af9e07ceabaadd1ba4cf327eeba0bb4f Mon Sep 17 00:00:00 2001 From: Sachin Date: Mon, 1 Oct 2018 15:15:34 +0530 Subject: Fix rpl_parallel_optimistic_nobinlog failure on binlog --- mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf index 0ea0d951568..b85a84f6625 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf @@ -5,5 +5,6 @@ log-slave-updates=0 loose-innodb [mysqld.2] +slave-transaction-retries=100 log-slave-updates=0 loose-innodb -- cgit v1.2.1 From 15803fce92a9e3ec7daab79d21990b499b1a709e Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Fri, 28 Sep 2018 19:57:06 +0300 Subject: MDEV-17313 Data race in ib_counter_t ib_counter_t: make all reads/writes to m_counter relaxed atomical --- storage/innobase/include/ut0counter.h | 46 ++++++++++++++++++++--------------- storage/xtradb/include/ut0counter.h | 46 ++++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 38 deletions(-) diff --git a/storage/innobase/include/ut0counter.h b/storage/innobase/include/ut0counter.h index edc0db3b03d..6fde8a7a638 100644 --- a/storage/innobase/include/ut0counter.h +++ b/storage/innobase/include/ut0counter.h @@ -32,6 +32,7 @@ Created 2012/04/12 by Sunny Bains #include #include "os0thread.h" #include "os0sync.h" +#include "my_atomic.h" /** Default number of slots to use in ib_counter_t */ #define IB_N_SLOTS 64 @@ -81,8 +82,8 @@ struct thread_id_indexer_t : public generic_indexer_t { } }; -/** Class for using fuzzy counters. The counter is not protected by any -mutex and the results are not guaranteed to be 100% accurate but close +/** Class for using fuzzy counters. The counter is relaxed atomic +so the results are not guaranteed to be 100% accurate but close enough. Creates an array of counters and separates each element by the CACHE_LINE_SIZE bytes */ template < @@ -91,20 +92,6 @@ template < template class Indexer = thread_id_indexer_t> struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t { -#ifdef UNIV_DEBUG - ~ib_counter_t() - { - size_t n = (CACHE_LINE_SIZE / sizeof(Type)); - - /* Check that we aren't writing outside our defined bounds. */ - for (size_t i = 0; i < UT_ARR_SIZE(m_counter); i += n) { - for (size_t j = 1; j < n - 1; ++j) { - ut_ad(m_counter[i + j] == 0); - } - } - } -#endif /* UNIV_DEBUG */ - /** Increment the counter by 1. */ void inc() UNIV_NOTHROW { add(1); } @@ -124,15 +111,36 @@ struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t ut_ad(i < UT_ARR_SIZE(m_counter)); - m_counter[i] += n; + if (sizeof(Type) == 8) { + my_atomic_add64_explicit( + reinterpret_cast(&m_counter[i]), + static_cast(n), MY_MEMORY_ORDER_RELAXED); + } else if (sizeof(Type) == 4) { + my_atomic_add32_explicit( + reinterpret_cast(&m_counter[i]), + static_cast(n), MY_MEMORY_ORDER_RELAXED); + } + compile_time_assert(sizeof(Type) == 8 || sizeof(Type) == 4); } - /* @return total value - not 100% accurate, since it is not atomic. */ + /* @return total value - not 100% accurate, since it is relaxed atomic. */ operator Type() const UNIV_NOTHROW { Type total = 0; for (size_t i = 0; i < N; ++i) { - total += m_counter[m_policy.offset(i)]; + if (sizeof(Type) == 8) { + total += static_cast< + Type>(my_atomic_load64_explicit( + reinterpret_cast(const_cast( + &m_counter[m_policy.offset(i)])), + MY_MEMORY_ORDER_RELAXED)); + } else if (sizeof(Type) == 4) { + total += static_cast< + Type>(my_atomic_load32_explicit( + reinterpret_cast(const_cast( + &m_counter[m_policy.offset(i)])), + MY_MEMORY_ORDER_RELAXED)); + } } return(total); diff --git a/storage/xtradb/include/ut0counter.h b/storage/xtradb/include/ut0counter.h index edc0db3b03d..6fde8a7a638 100644 --- a/storage/xtradb/include/ut0counter.h +++ b/storage/xtradb/include/ut0counter.h @@ -32,6 +32,7 @@ Created 2012/04/12 by Sunny Bains #include #include "os0thread.h" #include "os0sync.h" +#include "my_atomic.h" /** Default number of slots to use in ib_counter_t */ #define IB_N_SLOTS 64 @@ -81,8 +82,8 @@ struct thread_id_indexer_t : public generic_indexer_t { } }; -/** Class for using fuzzy counters. The counter is not protected by any -mutex and the results are not guaranteed to be 100% accurate but close +/** Class for using fuzzy counters. The counter is relaxed atomic +so the results are not guaranteed to be 100% accurate but close enough. Creates an array of counters and separates each element by the CACHE_LINE_SIZE bytes */ template < @@ -91,20 +92,6 @@ template < template class Indexer = thread_id_indexer_t> struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t { -#ifdef UNIV_DEBUG - ~ib_counter_t() - { - size_t n = (CACHE_LINE_SIZE / sizeof(Type)); - - /* Check that we aren't writing outside our defined bounds. */ - for (size_t i = 0; i < UT_ARR_SIZE(m_counter); i += n) { - for (size_t j = 1; j < n - 1; ++j) { - ut_ad(m_counter[i + j] == 0); - } - } - } -#endif /* UNIV_DEBUG */ - /** Increment the counter by 1. */ void inc() UNIV_NOTHROW { add(1); } @@ -124,15 +111,36 @@ struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t ut_ad(i < UT_ARR_SIZE(m_counter)); - m_counter[i] += n; + if (sizeof(Type) == 8) { + my_atomic_add64_explicit( + reinterpret_cast(&m_counter[i]), + static_cast(n), MY_MEMORY_ORDER_RELAXED); + } else if (sizeof(Type) == 4) { + my_atomic_add32_explicit( + reinterpret_cast(&m_counter[i]), + static_cast(n), MY_MEMORY_ORDER_RELAXED); + } + compile_time_assert(sizeof(Type) == 8 || sizeof(Type) == 4); } - /* @return total value - not 100% accurate, since it is not atomic. */ + /* @return total value - not 100% accurate, since it is relaxed atomic. */ operator Type() const UNIV_NOTHROW { Type total = 0; for (size_t i = 0; i < N; ++i) { - total += m_counter[m_policy.offset(i)]; + if (sizeof(Type) == 8) { + total += static_cast< + Type>(my_atomic_load64_explicit( + reinterpret_cast(const_cast( + &m_counter[m_policy.offset(i)])), + MY_MEMORY_ORDER_RELAXED)); + } else if (sizeof(Type) == 4) { + total += static_cast< + Type>(my_atomic_load32_explicit( + reinterpret_cast(const_cast( + &m_counter[m_policy.offset(i)])), + MY_MEMORY_ORDER_RELAXED)); + } } return(total); -- cgit v1.2.1 From 84a24d36d844841ba12ae93f708785ee63635336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 3 Oct 2018 08:49:57 +0300 Subject: MDEV-17357: Test failure on galera.galera_pc_ignore_sb Add wait until cluster has correct number of nodes. --- mysql-test/suite/galera/disabled.def | 2 +- mysql-test/suite/galera/r/galera_pc_ignore_sb.result | 6 +++++- mysql-test/suite/galera/t/galera_pc_ignore_sb.test | 20 +++++++++++++------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 92e45cc0f25..9a686b560b2 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -33,4 +33,4 @@ galera_gc_fc_limit : MDEV-17061 Test failure on galera.galera_gc_fc_limit partition : MDEV-13881 galera.partition failed in buildbot with wrong result galera_as_slave_replication_budle : MDEV-15785 Test case galera_as_slave_replication_bundle caused debug assertion galera_wan : MDEV-17259: Test failure on galera.galera_wan - +galera_pic_ignore_sb : MDEV-17357 Test failure on galera.galera_pc_ignore_sb diff --git a/mysql-test/suite/galera/r/galera_pc_ignore_sb.result b/mysql-test/suite/galera/r/galera_pc_ignore_sb.result index 5fcccfe2d59..81892a6cb38 100644 --- a/mysql-test/suite/galera/r/galera_pc_ignore_sb.result +++ b/mysql-test/suite/galera/r/galera_pc_ignore_sb.result @@ -1,4 +1,6 @@ -SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; +SET @wsrep_cluster_address_orig = @@GLOBAL.wsrep_cluster_address; +SET @wsrep_provider_options_orig = @@GLOBAL.wsrep_provider_options; +SET GLOBAL wsrep_provider_options ='pc.ignore_sb=true'; Killing server ... CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); @@ -10,3 +12,5 @@ SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABL VARIABLE_VALUE = 'ON' 1 SET GLOBAL wsrep_cluster_address = ''; +SET GLOBAL wsrep_cluster_address = @wsrep_cluster_address_orig; +SET GLOBAL wsrep_provider_options = @wsrep_provider_options_orig; diff --git a/mysql-test/suite/galera/t/galera_pc_ignore_sb.test b/mysql-test/suite/galera/t/galera_pc_ignore_sb.test index f24ca5cd25b..6ae2079577f 100644 --- a/mysql-test/suite/galera/t/galera_pc_ignore_sb.test +++ b/mysql-test/suite/galera/t/galera_pc_ignore_sb.test @@ -11,10 +11,13 @@ --source include/auto_increment_offset_save.inc --connection node_1 ---let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` ---let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET @wsrep_cluster_address_orig = @@GLOBAL.wsrep_cluster_address; +SET @wsrep_provider_options_orig = @@GLOBAL.wsrep_provider_options; -SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +SET GLOBAL wsrep_provider_options ='pc.ignore_sb=true'; --connection node_2 --source include/kill_galera.inc @@ -33,14 +36,17 @@ SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABL # Reset the master and restart the slave so that post-test checks can run SET GLOBAL wsrep_cluster_address = ''; ---disable_query_log ---eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; ---eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig'; ---enable_query_log +SET GLOBAL wsrep_cluster_address = @wsrep_cluster_address_orig; --connection node_2 --source include/start_mysqld.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options = @wsrep_provider_options_orig; + # Restore original auto_increment_offset values. --source include/auto_increment_offset_restore.inc -- cgit v1.2.1 From e2a1c58582ac25af0af0621a2c32d822a5e9cecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 3 Oct 2018 08:58:23 +0300 Subject: Fix test failure on wsrep.variables SLES11 can't build currently latest Galera library version. --- mysql-test/suite/wsrep/t/variables.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/wsrep/t/variables.test b/mysql-test/suite/wsrep/t/variables.test index 15104b9b654..1a2ab2579a5 100644 --- a/mysql-test/suite/wsrep/t/variables.test +++ b/mysql-test/suite/wsrep/t/variables.test @@ -30,7 +30,7 @@ CALL mtr.add_suppression("WSREP: Could not open saved state file for reading.*") --disable_result_log --disable_query_log eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; ---let $galera_version=25.3.17 +--let $galera_version=25.3.24 source include/check_galera_version.inc; --enable_result_log --enable_query_log -- cgit v1.2.1 From 391b7f5bd190c3fcbaedf1128a6bc3e7f9981efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 4 Oct 2018 08:04:55 +0300 Subject: Fix typo. --- mysql-test/suite/galera/disabled.def | 2 +- mysql-test/suite/galera/t/galera_pc_ignore_sb.test | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 9a686b560b2..464ed6444f9 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -33,4 +33,4 @@ galera_gc_fc_limit : MDEV-17061 Test failure on galera.galera_gc_fc_limit partition : MDEV-13881 galera.partition failed in buildbot with wrong result galera_as_slave_replication_budle : MDEV-15785 Test case galera_as_slave_replication_bundle caused debug assertion galera_wan : MDEV-17259: Test failure on galera.galera_wan -galera_pic_ignore_sb : MDEV-17357 Test failure on galera.galera_pc_ignore_sb +galera_pc_ignore_sb : MDEV-17357 Test failure on galera.galera_pc_ignore_sb diff --git a/mysql-test/suite/galera/t/galera_pc_ignore_sb.test b/mysql-test/suite/galera/t/galera_pc_ignore_sb.test index 6ae2079577f..c48ddc66bdf 100644 --- a/mysql-test/suite/galera/t/galera_pc_ignore_sb.test +++ b/mysql-test/suite/galera/t/galera_pc_ignore_sb.test @@ -41,10 +41,11 @@ SET GLOBAL wsrep_cluster_address = @wsrep_cluster_address_orig; --connection node_2 --source include/start_mysqld.inc + +--connection node_1 --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' --source include/wait_condition.inc ---connection node_1 SET GLOBAL wsrep_provider_options = @wsrep_provider_options_orig; # Restore original auto_increment_offset values. -- cgit v1.2.1 From 6c29544c20968bad607456dc94c4fd5bd787e9f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 4 Oct 2018 08:05:50 +0300 Subject: Enable for staging tree. --- mysql-test/suite/galera/disabled.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 464ed6444f9..efd02a14fec 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -33,4 +33,4 @@ galera_gc_fc_limit : MDEV-17061 Test failure on galera.galera_gc_fc_limit partition : MDEV-13881 galera.partition failed in buildbot with wrong result galera_as_slave_replication_budle : MDEV-15785 Test case galera_as_slave_replication_bundle caused debug assertion galera_wan : MDEV-17259: Test failure on galera.galera_wan -galera_pc_ignore_sb : MDEV-17357 Test failure on galera.galera_pc_ignore_sb +#galera_pc_ignore_sb : MDEV-17357 Test failure on galera.galera_pc_ignore_sb -- cgit v1.2.1 From e855912733287d496cb2f429c8019005aaac9d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 4 Oct 2018 13:29:29 +0300 Subject: Test by reverting MDEV-16656: DROP DATABASE crashes the Galera Cluster --- mysql-test/suite/galera/disabled.def | 3 ++- storage/innobase/fts/fts0fts.cc | 25 +++---------------------- storage/xtradb/fts/fts0fts.cc | 25 +++---------------------- 3 files changed, 8 insertions(+), 45 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index efd02a14fec..603031f52b7 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -33,4 +33,5 @@ galera_gc_fc_limit : MDEV-17061 Test failure on galera.galera_gc_fc_limit partition : MDEV-13881 galera.partition failed in buildbot with wrong result galera_as_slave_replication_budle : MDEV-15785 Test case galera_as_slave_replication_bundle caused debug assertion galera_wan : MDEV-17259: Test failure on galera.galera_wan -#galera_pc_ignore_sb : MDEV-17357 Test failure on galera.galera_pc_ignore_sb +galera_pc_ignore_sb : MDEV-17357 Test failure on galera.galera_pc_ignore_sb +galera_drop_database : test diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 04aaff96b91..a5b2bbb47ce 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -2762,7 +2762,7 @@ retry: mutex_enter(&cache->doc_id_lock); /* For each sync operation, we will add next_doc_id by 1, so to mark a sync operation */ - if (cache->next_doc_id <= cache->synced_doc_id) { + if (cache->next_doc_id < cache->synced_doc_id + 1) { cache->next_doc_id = cache->synced_doc_id + 1; } mutex_exit(&cache->doc_id_lock); @@ -6665,6 +6665,7 @@ fts_rename_aux_tables_to_hex_format( "All the fts index associated with the table are " "marked as corrupted. Please rebuild the " "index again.", parent_table->name); + fts_sql_rollback(trx_rename); /* Corrupting the fts index related to parent table. */ trx_t* trx_corrupt; @@ -7041,27 +7042,7 @@ fts_check_and_drop_orphaned_tables( /* If the aux table is in decimal format, we should rename it, so push it to aux_tables_to_rename */ if (!drop && rename) { - /* It is necessary to check that the table with - this name is missing in the vector - otherwise it - can be renamed twice: */ - bool rename_table = true; - for (ulint count = 0; - count < ib_vector_size(aux_tables_to_rename); - count++) { - fts_aux_table_t* rename_aux = - static_cast( - ib_vector_get(aux_tables_to_rename, - count)); - if (strcmp(rename_aux->name, - aux_table->name) == 0) { - rename_table = false; - break; - } - } - if (rename_table) { - ib_vector_push(aux_tables_to_rename, - aux_table); - } + ib_vector_push(aux_tables_to_rename, aux_table); } if (i + 1 < ib_vector_size(tables)) { diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index d5128955f56..5981c24c470 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/fts/fts0fts.cc @@ -2761,7 +2761,7 @@ retry: mutex_enter(&cache->doc_id_lock); /* For each sync operation, we will add next_doc_id by 1, so to mark a sync operation */ - if (cache->next_doc_id <= cache->synced_doc_id) { + if (cache->next_doc_id < cache->synced_doc_id + 1) { cache->next_doc_id = cache->synced_doc_id + 1; } mutex_exit(&cache->doc_id_lock); @@ -6664,6 +6664,7 @@ fts_rename_aux_tables_to_hex_format( "All the fts index associated with the table are " "marked as corrupted. Please rebuild the " "index again.", parent_table->name); + fts_sql_rollback(trx_rename); /* Corrupting the fts index related to parent table. */ trx_t* trx_corrupt; @@ -7040,27 +7041,7 @@ fts_check_and_drop_orphaned_tables( /* If the aux table is in decimal format, we should rename it, so push it to aux_tables_to_rename */ if (!drop && rename) { - /* It is necessary to check that the table with - this name is missing in the vector - otherwise it - can be renamed twice: */ - bool rename_table = true; - for (ulint count = 0; - count < ib_vector_size(aux_tables_to_rename); - count++) { - fts_aux_table_t* rename_aux = - static_cast( - ib_vector_get(aux_tables_to_rename, - count)); - if (strcmp(rename_aux->name, - aux_table->name) == 0) { - rename_table = false; - break; - } - } - if (rename_table) { - ib_vector_push(aux_tables_to_rename, - aux_table); - } + ib_vector_push(aux_tables_to_rename, aux_table); } if (i + 1 < ib_vector_size(tables)) { -- cgit v1.2.1 From 1655053ac1c0b175d860defa2819b29642f664a7 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 21 Sep 2018 16:04:16 +0400 Subject: MDEV-17200 - pthread_detach called for already detached threads pthread_detach_this_thread() was intended to be defined to something meaningful only on some ancient unixes, which don't have pthread_attr_setdetachstate() defined. Otherwise, on normal unixes, threads are created detached in the first place. This was broken in 0f01bf267680244ec488adaf65a42838756ed48e so that we started calling pthread_detach() for already detached threads. Intention was to detach aria checkpoint thread. However in 87007dc2f71634cc460271eb277ad851ec69c04b aria service threads were made joinable with appropriate handling, which makes breaking revision unneccessary. Revert remnants of 0f01bf267680244ec488adaf65a42838756ed48e, so that pthread_detach_this_thread() is meaningful only on some ancient unixes again. --- include/my_pthread.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index 6b830ca36d2..ae2f912f979 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -184,7 +184,7 @@ int pthread_cancel(pthread_t thread); #define pthread_key(T,V) pthread_key_t V #define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V)) #define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V)) -#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); } +#define pthread_detach_this_thread() #define pthread_handler_t EXTERNC void * typedef void *(* pthread_handler)(void *); -- cgit v1.2.1 From 2f4a0c5be2c5d5153c4253a49ba8820ab333a9a0 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sun, 7 Oct 2018 18:59:52 +0200 Subject: Fix accumulation of old rows in mysql.gtid_slave_pos This would happen especially in optimistic parallel replication, where there is a good chance that a transaction will be rolled back (due to conflicts) after it has executed record_gtid(). If the transaction did any deletions of old rows as part of record_gtid(), those deletions will be undone as well. And the code did not properly ensure that the deletions would be re-tried. This patch makes record_gtid() remember the list of deletions done as part of a transaction. Then in rpl_slave_state::update() when the changes have been committed, we discard the list. However, in case of error and rollback, in cleanup_context() we will instead put the list back into rpl_global_gtid_slave_state so that the deletions will be re-tried later. Probably fixes part of the cause of MDEV-12147 as well. Signed-off-by: Kristian Nielsen --- .../suite/rpl/r/rpl_parallel_optimistic.result | 6 ++ .../suite/rpl/t/rpl_parallel_optimistic.test | 17 +++++ sql/log_event.cc | 6 +- sql/rpl_gtid.cc | 64 ++++++++++++------ sql/rpl_gtid.h | 2 +- sql/rpl_rli.cc | 79 ++++++++++++++++++++++ sql/rpl_rli.h | 11 +++ 7 files changed, 161 insertions(+), 24 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result index 3cd4f8231bf..99bd8562ffe 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result @@ -571,4 +571,10 @@ SET GLOBAL slave_parallel_mode=@old_parallel_mode; SET GLOBAL slave_parallel_threads=@old_parallel_threads; include/start_slave.inc DROP TABLE t1, t2, t3; +include/save_master_gtid.inc +include/sync_with_master_gtid.inc +Check that no more than the expected last two GTIDs are in mysql.gtid_slave_pos +select count(*) from mysql.gtid_slave_pos order by domain_id, sub_id; +count(*) +2 include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test index 9f6669279db..3867a3fdf3a 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test @@ -549,5 +549,22 @@ SET GLOBAL slave_parallel_threads=@old_parallel_threads; --connection server_1 DROP TABLE t1, t2, t3; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +# Check for left-over rows in table mysql.gtid_slave_pos (MDEV-12147). +# +# There was a bug when a transaction got a conflict and was rolled back. It +# might have also handled deletion of some old rows, and these deletions would +# then also be rolled back. And since the deletes were never re-tried, old no +# longer needed rows would accumulate in the table without limit. +# +# The earlier part of this test file have plenty of transactions being rolled +# back. But the last DROP TABLE statement runs on its own and should never +# conflict, thus at this point the mysql.gtid_slave_pos table should be clean. +--echo Check that no more than the expected last two GTIDs are in mysql.gtid_slave_pos +select count(*) from mysql.gtid_slave_pos order by domain_id, sub_id; +--connection server_1 --source include/rpl_end.inc diff --git a/sql/log_event.cc b/sql/log_event.cc index e1912ad4620..e07b7002398 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -4429,7 +4429,7 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi, gtid= rgi->current_gtid; if (rpl_global_gtid_slave_state->record_gtid(thd, >id, sub_id, - true, false)) + rgi, false)) { int errcode= thd->get_stmt_da()->sql_errno(); if (!is_parallel_retry_error(rgi, errcode)) @@ -7132,7 +7132,7 @@ Gtid_list_log_event::do_apply_event(rpl_group_info *rgi) { if ((ret= rpl_global_gtid_slave_state->record_gtid(thd, &list[i], sub_id_list[i], - false, false))) + NULL, false))) return ret; rpl_global_gtid_slave_state->update_state_hash(sub_id_list[i], &list[i], NULL); @@ -7639,7 +7639,7 @@ int Xid_log_event::do_apply_event(rpl_group_info *rgi) rgi->gtid_pending= false; gtid= rgi->current_gtid; - err= rpl_global_gtid_slave_state->record_gtid(thd, >id, sub_id, true, + err= rpl_global_gtid_slave_state->record_gtid(thd, >id, sub_id, rgi, false); if (err) { diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 7b1acf17ef5..94944b5b3e5 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -77,7 +77,7 @@ rpl_slave_state::record_and_update_gtid(THD *thd, rpl_group_info *rgi) rgi->gtid_pending= false; if (rgi->gtid_ignore_duplicate_state!=rpl_group_info::GTID_DUPLICATE_IGNORE) { - if (record_gtid(thd, &rgi->current_gtid, sub_id, false, false)) + if (record_gtid(thd, &rgi->current_gtid, sub_id, NULL, false)) DBUG_RETURN(1); update_state_hash(sub_id, &rgi->current_gtid, rgi); } @@ -328,6 +328,8 @@ rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id, } } rgi->gtid_ignore_duplicate_state= rpl_group_info::GTID_DUPLICATE_NULL; + + rgi->pending_gtid_deletes_clear(); } if (!(list_elem= (list_element *)my_malloc(sizeof(*list_elem), MYF(MY_WME)))) @@ -377,15 +379,24 @@ int rpl_slave_state::put_back_list(uint32 domain_id, list_element *list) { element *e; + int err= 0; + + mysql_mutex_lock(&LOCK_slave_state); if (!(e= (element *)my_hash_search(&hash, (const uchar *)&domain_id, 0))) - return 1; + { + err= 1; + goto end; + } while (list) { list_element *next= list->next; e->add(list); list= next; } - return 0; + +end: + mysql_mutex_unlock(&LOCK_slave_state); + return err; } @@ -468,12 +479,12 @@ gtid_check_rpl_slave_state_table(TABLE *table) /* Write a gtid to the replication slave state table. - Do it as part of the transaction, to get slave crash safety, or as a separate - transaction if !in_transaction (eg. MyISAM or DDL). - gtid The global transaction id for this event group. sub_id Value allocated within the sub_id when the event group was read (sub_id must be consistent with commit order in master binlog). + rgi rpl_group_info context, if we are recording the gtid transactionally + as part of replicating a transactional event. NULL if called from + outside of a replicated transaction. Note that caller must later ensure that the new gtid and sub_id is inserted into the appropriate HASH element with rpl_slave_state.add(), so that it can @@ -481,13 +492,13 @@ gtid_check_rpl_slave_state_table(TABLE *table) */ int rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, - bool in_transaction, bool in_statement) + rpl_group_info *rgi, bool in_statement) { TABLE_LIST tlist; int err= 0; bool table_opened= false; TABLE *table; - list_element *elist= 0, *next; + list_element *elist= 0, *cur, *next; element *elem; ulonglong thd_saved_option= thd->variables.option_bits; Query_tables_list lex_backup; @@ -558,7 +569,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, thd->wsrep_ignore_table= true; #endif - if (!in_transaction) + if (!rgi) { DBUG_PRINT("info", ("resetting OPTION_BEGIN")); thd->variables.option_bits&= @@ -601,9 +612,9 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, if ((elist= elem->grab_list()) != NULL) { /* Delete any old stuff, but keep around the most recent one. */ - list_element *cur= elist; - uint64 best_sub_id= cur->sub_id; + uint64 best_sub_id= elist->sub_id; list_element **best_ptr_ptr= &elist; + cur= elist; while ((next= cur->next)) { if (next->sub_id > best_sub_id) @@ -636,7 +647,8 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, table->file->print_error(err, MYF(0)); goto end; } - while (elist) + cur = elist; + while (cur) { uchar key_buffer[4+8]; @@ -646,9 +658,9 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, /* `break' does not work inside DBUG_EXECUTE_IF */ goto dbug_break; }); - next= elist->next; + next= cur->next; - table->field[1]->store(elist->sub_id, true); + table->field[1]->store(cur->sub_id, true); /* domain_id is already set in table->record[0] from write_row() above. */ key_copy(key_buffer, table->record[0], &table->key_info[0], 0, false); if (table->file->ha_index_read_map(table->record[1], key_buffer, @@ -662,8 +674,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, not want to endlessly error on the same element in case of table corruption or such. */ - my_free(elist); - elist= next; + cur= next; if (err) break; } @@ -686,18 +697,31 @@ end: */ if (elist) { - mysql_mutex_lock(&LOCK_slave_state); put_back_list(gtid->domain_id, elist); - mysql_mutex_unlock(&LOCK_slave_state); + elist = 0; } ha_rollback_trans(thd, FALSE); } close_thread_tables(thd); - if (in_transaction) + if (rgi) + { thd->mdl_context.release_statement_locks(); + /* + Save the list of old gtid entries we deleted. If this transaction + fails later for some reason and is rolled back, the deletion of those + entries will be rolled back as well, and we will need to put them back + on the to-be-deleted list so we can re-do the deletion. Otherwise + redundant rows in mysql.gtid_slave_pos may accumulate if transactions + are rolled back and retried after record_gtid(). + */ + rgi->pending_gtid_deletes_save(gtid->domain_id, elist); + } else + { thd->mdl_context.release_transactional_locks(); + rpl_group_info::pending_gtid_deletes_free(elist); + } } thd->lex->restore_backup_query_tables_list(&lex_backup); thd->variables.option_bits= thd_saved_option; @@ -1080,7 +1104,7 @@ rpl_slave_state::load(THD *thd, char *state_from_master, size_t len, if (gtid_parser_helper(&state_from_master, end, >id) || !(sub_id= next_sub_id(gtid.domain_id)) || - record_gtid(thd, >id, sub_id, false, in_statement) || + record_gtid(thd, >id, sub_id, NULL, in_statement) || update(gtid.domain_id, gtid.server_id, sub_id, gtid.seq_no, NULL)) return 1; if (state_from_master == end) diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h index 79d566bddbf..7bd639b768f 100644 --- a/sql/rpl_gtid.h +++ b/sql/rpl_gtid.h @@ -182,7 +182,7 @@ struct rpl_slave_state uint64 seq_no, rpl_group_info *rgi); int truncate_state_table(THD *thd); int record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, - bool in_transaction, bool in_statement); + rpl_group_info *rgi, bool in_statement); uint64 next_sub_id(uint32 domain_id); int iterate(int (*cb)(rpl_gtid *, void *), void *data, rpl_gtid *extra_gtids, uint32 num_extra, diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 64a1b535307..b35130c1505 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1680,6 +1680,7 @@ rpl_group_info::reinit(Relay_log_info *rli) long_find_row_note_printed= false; did_mark_start_commit= false; gtid_ev_flags2= 0; + pending_gtid_delete_list= NULL; last_master_timestamp = 0; gtid_ignore_duplicate_state= GTID_DUPLICATE_NULL; speculation= SPECULATE_NO; @@ -1804,6 +1805,12 @@ void rpl_group_info::cleanup_context(THD *thd, bool error) erroneously update the GTID position. */ gtid_pending= false; + + /* + Rollback will have undone any deletions of old rows we might have made + in mysql.gtid_slave_pos. Put those rows back on the list to be deleted. + */ + pending_gtid_deletes_put_back(); } m_table_map.clear_tables(); slave_close_thread_tables(thd); @@ -2027,6 +2034,78 @@ rpl_group_info::unmark_start_commit() } +/* + When record_gtid() has deleted any old rows from the table + mysql.gtid_slave_pos as part of a replicated transaction, save the list of + rows deleted here. + + If later the transaction fails (eg. optimistic parallel replication), the + deletes will be undone when the transaction is rolled back. Then we can + put back the list of rows into the rpl_global_gtid_slave_state, so that + we can re-do the deletes and avoid accumulating old rows in the table. +*/ +void +rpl_group_info::pending_gtid_deletes_save(uint32 domain_id, + rpl_slave_state::list_element *list) +{ + /* + We should never get to a state where we try to save a new pending list of + gtid deletes while we still have an old one. But make sure we handle it + anyway just in case, so we avoid leaving stray entries in the + mysql.gtid_slave_pos table. + */ + DBUG_ASSERT(!pending_gtid_delete_list); + if (unlikely(pending_gtid_delete_list)) + pending_gtid_deletes_put_back(); + + pending_gtid_delete_list= list; + pending_gtid_delete_list_domain= domain_id; +} + + +/* + Take the list recorded by pending_gtid_deletes_save() and put it back into + rpl_global_gtid_slave_state. This is needed if deletion of the rows was + rolled back due to transaction failure. +*/ +void +rpl_group_info::pending_gtid_deletes_put_back() +{ + if (pending_gtid_delete_list) + { + rpl_global_gtid_slave_state->put_back_list(pending_gtid_delete_list_domain, + pending_gtid_delete_list); + pending_gtid_delete_list= NULL; + } +} + + +/* + Free the list recorded by pending_gtid_deletes_save(). Done when the deletes + in the list have been permanently committed. +*/ +void +rpl_group_info::pending_gtid_deletes_clear() +{ + pending_gtid_deletes_free(pending_gtid_delete_list); + pending_gtid_delete_list= NULL; +} + + +void +rpl_group_info::pending_gtid_deletes_free(rpl_slave_state::list_element *list) +{ + rpl_slave_state::list_element *next; + + while (list) + { + next= list->next; + my_free(list); + list= next; + } +} + + rpl_sql_thread_info::rpl_sql_thread_info(Rpl_filter *filter) : rpl_filter(filter) { diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index 74d5b6fe416..b40a34a54e6 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -676,6 +676,11 @@ struct rpl_group_info /* Needs room for "Gtid D-S-N\x00". */ char gtid_info_buf[5+10+1+10+1+20+1]; + /* List of not yet committed deletions in mysql.gtid_slave_pos. */ + rpl_slave_state::list_element *pending_gtid_delete_list; + /* Domain associated with pending_gtid_delete_list. */ + uint32 pending_gtid_delete_list_domain; + /* The timestamp, from the master, of the commit event. Used to do delayed update of rli->last_master_timestamp, for getting @@ -817,6 +822,12 @@ struct rpl_group_info char *gtid_info(); void unmark_start_commit(); + static void pending_gtid_deletes_free(rpl_slave_state::list_element *list); + void pending_gtid_deletes_save(uint32 domain_id, + rpl_slave_state::list_element *list); + void pending_gtid_deletes_put_back(); + void pending_gtid_deletes_clear(); + time_t get_row_stmt_start_timestamp() { return row_stmt_start_timestamp; -- cgit v1.2.1 From 1eca49577e979220f3ab663a7e46e0eb70d728c4 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sun, 7 Oct 2018 10:19:19 -0700 Subject: MDEV-17382 Hash join algorithm should not be used to join materialized derived table / view by equality Now rows of a materialized derived table are always put into a temporary table before join operation. If BNLH is used to join this table with the result of a partial join then both operands of the join are actually put into main memory. In most cases this is not efficient. We could avoid this by sending the rows of the derived table directly to the join operation. However this kind of data flow is not supported yet. Fixed by not allowing usage of hash join algorithm to join a materialized derived table if it's joined by an equality predicate of the form f=e where f is a field of the derived table. --- mysql-test/r/derived_opt.result | 35 ++++++++++++++++++++++++++++++++++- mysql-test/r/innodb_mrr_cpk.result | 2 +- mysql-test/t/derived_opt.test | 38 ++++++++++++++++++++++++++++++++++++++ sql/sql_select.cc | 8 ++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/derived_opt.result b/mysql-test/r/derived_opt.result index 04a76c2cbc8..63d2c432768 100644 --- a/mysql-test/r/derived_opt.result +++ b/mysql-test/r/derived_opt.result @@ -499,9 +499,42 @@ where D1.a= t1.a; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where -1 PRIMARY hash_ALL key0 #hash#key0 5 test.t1.a 100 Using join buffer (flat, BNLH join) +1 PRIMARY ref key0 key0 5 test.t1.a 10 2 DERIVED t2 ALL NULL NULL NULL NULL 100 Using filesort set join_cache_level=@tmp_jcl; set optimizer_switch=@tmp_os; drop table t1, t2; +# +# Bug mdev-17382: equi-join of derived table with join_cache_level=4 +# +CREATE TABLE t1 ( +id int NOT NULL, +amount decimal DEFAULT NULL, +PRIMARY KEY (id) +); +CREATE TABLE t2 ( +id int NOT NULL, +name varchar(50) DEFAULT NULL, +PRIMARY KEY (id) +); +INSERT INTO t1 VALUES +(1, 10.0000), (2, 20.0000), (3, 30.0000), (4, 40.0000), +(5, NULL), (6, NULL), (7, 70.0000), (8, 80.0000); +INSERT INTO t2 VALUES +(1,'A'), (2,'B'), (3,'C'), (4,'D'), (5, NULL), (6, NULL), +(7,'E'), (8,'F'), (9,'G'), (10,'H'), (11, NULL), (12, NULL); +set join_cache_level=4; +EXPLAIN +SELECT t2.id,t2.name,t.total_amt +FROM t2 +LEFT JOIN +(SELECT id, sum(amount) total_amt FROM t1 GROUP BY id) AS t +ON t2.id=t.id +WHERE t2.id < 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 range PRIMARY PRIMARY 4 NULL 3 Using index condition +1 PRIMARY ref key0 key0 5 test.t2.id 2 +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using temporary; Using filesort +set join_cache_level=default; +DROP TABLE t1,t2; set optimizer_switch=@exit_optimizer_switch; diff --git a/mysql-test/r/innodb_mrr_cpk.result b/mysql-test/r/innodb_mrr_cpk.result index 28d7dd51df8..a2e43d7d127 100644 --- a/mysql-test/r/innodb_mrr_cpk.result +++ b/mysql-test/r/innodb_mrr_cpk.result @@ -226,7 +226,7 @@ set join_cache_level=3; explain SELECT 1 FROM (SELECT url, id FROM t2 LIMIT 1 OFFSET 20) derived RIGHT JOIN t1 ON t1.id = derived.id; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL # -1 PRIMARY hash_ALL key0 #hash#key0 25 test.t1.id # Using join buffer (flat, BNLH join) +1 PRIMARY ref key0 key0 25 test.t1.id # 2 DERIVED t2 ALL NULL NULL NULL NULL # set join_cache_level= @tmp_mdev5037; drop table t0,t1,t2; diff --git a/mysql-test/t/derived_opt.test b/mysql-test/t/derived_opt.test index 7f19553e4e5..aab95f69f26 100644 --- a/mysql-test/t/derived_opt.test +++ b/mysql-test/t/derived_opt.test @@ -363,5 +363,43 @@ set join_cache_level=@tmp_jcl; set optimizer_switch=@tmp_os; drop table t1, t2; +--echo # +--echo # Bug mdev-17382: equi-join of derived table with join_cache_level=4 +--echo # + +CREATE TABLE t1 ( + id int NOT NULL, + amount decimal DEFAULT NULL, +PRIMARY KEY (id) +); + +CREATE TABLE t2 ( + id int NOT NULL, + name varchar(50) DEFAULT NULL, +PRIMARY KEY (id) +); + +INSERT INTO t1 VALUES +(1, 10.0000), (2, 20.0000), (3, 30.0000), (4, 40.0000), +(5, NULL), (6, NULL), (7, 70.0000), (8, 80.0000); + +INSERT INTO t2 VALUES +(1,'A'), (2,'B'), (3,'C'), (4,'D'), (5, NULL), (6, NULL), +(7,'E'), (8,'F'), (9,'G'), (10,'H'), (11, NULL), (12, NULL); + +set join_cache_level=4; + +EXPLAIN +SELECT t2.id,t2.name,t.total_amt + FROM t2 + LEFT JOIN + (SELECT id, sum(amount) total_amt FROM t1 GROUP BY id) AS t + ON t2.id=t.id + WHERE t2.id < 3; + +set join_cache_level=default; + +DROP TABLE t1,t2; + # The following command must be the last one the file set optimizer_switch=@exit_optimizer_switch; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fa0be81ff3d..62f40eeb99c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11005,7 +11005,15 @@ uint check_join_cache_usage(JOIN_TAB *tab, effort now. */ if (tab->table->pos_in_table_list->is_materialized_derived()) + { no_bka_cache= true; + /* + Don't use hash join algorithm if the temporary table for the rows + of the derived table will be created with an equi-join key. + */ + if (tab->table->s->keys) + no_hashed_cache= true; + } /* Don't use join buffering if we're dictated not to by no_jbuf_after -- cgit v1.2.1 From f517d8c7425257b6b9fe81c82c489e1e5619898d Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Tue, 2 Oct 2018 14:30:44 +0300 Subject: MDEV-17346 parallel slave start and stop races to workers disappeared The bug appears as a slave SQL thread hanging in rpl_parallel_thread_pool::get_thread() while there are no slave worker threads to awake it. The reason of the hang is that at the parallel slave worker pool activation the being stared SQL thread could read the worker pool size concurrently with pool deactivation. At reading the SQL thread did not employ necessary protection from a race. Fixed with making the SQL thread at the pool activation first to grab the same lock as potential deactivator also does prior to access the pool size. --- sql/rpl_parallel.cc | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 35cddee6d4d..8fef2d66635 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -1617,13 +1617,32 @@ int rpl_parallel_resize_pool_if_no_slaves(void) } +/** + Pool activation is preceeded by taking a "lock" of pool_mark_busy + which guarantees the number of running slaves drops to zero atomicly + with the number of pool workers. + This resolves race between the function caller thread and one + that may be attempting to deactivate the pool. +*/ int rpl_parallel_activate_pool(rpl_parallel_thread_pool *pool) { + int rc= 0; + + if ((rc= pool_mark_busy(pool, current_thd))) + return rc; // killed + if (!pool->count) - return rpl_parallel_change_thread_count(pool, opt_slave_parallel_threads, - 0); - return 0; + { + pool_mark_not_busy(pool); + rc= rpl_parallel_change_thread_count(pool, opt_slave_parallel_threads, + 0); + } + else + { + pool_mark_not_busy(pool); + } + return rc; } -- cgit v1.2.1 From 5b0b6660f6010dbd9fe8807af72ddba4d9b73781 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 9 Oct 2018 18:34:37 +0100 Subject: MDEV-17413 - Don't crash in my_malloc_size_cb_func() if thread specific memory is requested and current_thd is NULL. Leave DBUG_ASSERT() in place, to check in DBUG version. --- sql/mysqld.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3dff49f5ccb..c2fdb5a4026 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3907,14 +3907,16 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) { THD *thd= current_thd; - if (is_thread_specific) /* If thread specific memory */ - { - /* - When thread specfic is set, both mysqld_server_initialized and thd - must be set - */ - DBUG_ASSERT(mysqld_server_initialized && thd); + /* + When thread specific is set, both mysqld_server_initialized and thd + must be set, and we check that with DBUG_ASSERT. + However, do not crash, if current_thd is NULL, in release version. + */ + DBUG_ASSERT(!is_thread_specific || (mysqld_server_initialized && thd)); + + if (is_thread_specific && likely(thd)) /* If thread specific memory */ + { DBUG_PRINT("info", ("thd memory_used: %lld size: %lld", (longlong) thd->status_var.local_memory_used, size)); -- cgit v1.2.1 From 3c3c4ae22545d3242a8b7c4f2bec3bf2d245890a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 10 Oct 2018 09:14:16 +0300 Subject: MDEV-17403: Test failure on galera.galera_enum Add wait on second node. --- mysql-test/suite/galera/r/galera_enum.result | 37 ++++++++++++++++------------ mysql-test/suite/galera/t/galera_enum.test | 18 +++++++++----- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_enum.result b/mysql-test/suite/galera/r/galera_enum.result index e853c5c9943..7b42aab264c 100644 --- a/mysql-test/suite/galera/r/galera_enum.result +++ b/mysql-test/suite/galera/r/galera_enum.result @@ -4,23 +4,23 @@ INSERT INTO t1 VALUES ('one'), ('two'); INSERT INTO t1 VALUES (0), (1), (2); Warnings: Warning 1265 Data truncated for column 'f1' at row 1 -SELECT COUNT(*) = 6 FROM t1; -COUNT(*) = 6 -1 -SELECT COUNT(*) = 2 FROM t1 where f1 = ''; -COUNT(*) = 2 -1 -SELECT COUNT(*) = 2 FROM t1 where f1 = 'one'; -COUNT(*) = 2 -1 +SELECT COUNT(*) FROM t1; +COUNT(*) +6 +SELECT COUNT(*) FROM t1 where f1 = ''; +COUNT(*) +2 +SELECT COUNT(*) FROM t1 where f1 = 'one'; +COUNT(*) +2 DROP TABLE t1; CREATE TABLE t1 (f1 ENUM('', 'one', 'two', 'three', 'four') PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (''), ('one'), ('two'); -SELECT COUNT(*) = 3 FROM t1; -COUNT(*) = 3 -1 -SELECT COUNT(*) = 1 FROM t1 WHERE f1 = ''; -COUNT(*) = 1 +SELECT COUNT(*) FROM t1; +COUNT(*) +3 +SELECT COUNT(*) FROM t1 WHERE f1 = ''; +COUNT(*) 1 SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -31,7 +31,12 @@ UPDATE t1 SET f1 = 'four' where f1 = ''; COMMIT; COMMIT; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'three'; -COUNT(*) = 1 +SELECT COUNT(*) FROM t1 WHERE f1 = 'three'; +COUNT(*) 1 +SELECT * FROM t1; +f1 +one +two +three DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_enum.test b/mysql-test/suite/galera/t/galera_enum.test index ff5332486aa..782180a3aa1 100644 --- a/mysql-test/suite/galera/t/galera_enum.test +++ b/mysql-test/suite/galera/t/galera_enum.test @@ -17,9 +17,12 @@ INSERT INTO t1 VALUES ('one'), ('two'); INSERT INTO t1 VALUES (0), (1), (2); --connection node_2 -SELECT COUNT(*) = 6 FROM t1; -SELECT COUNT(*) = 2 FROM t1 where f1 = ''; -SELECT COUNT(*) = 2 FROM t1 where f1 = 'one'; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1'; +--source include/wait_condition.inc + +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t1 where f1 = ''; +SELECT COUNT(*) FROM t1 where f1 = 'one'; DROP TABLE t1; @@ -33,8 +36,10 @@ CREATE TABLE t1 (f1 ENUM('', 'one', 'two', 'three', 'four') PRIMARY KEY) ENGINE= INSERT INTO t1 VALUES (''), ('one'), ('two'); --connection node_2 -SELECT COUNT(*) = 3 FROM t1; -SELECT COUNT(*) = 1 FROM t1 WHERE f1 = ''; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t1'; +--source include/wait_condition.inc +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t1 WHERE f1 = ''; # Conflict @@ -57,6 +62,7 @@ COMMIT; --connection node_1 -SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'three'; +SELECT COUNT(*) FROM t1 WHERE f1 = 'three'; +SELECT * FROM t1; DROP TABLE t1; -- cgit v1.2.1 From 8d116d1686de3086b4b85d149e8ef0a4fdd3ad0d Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 10 Oct 2018 14:39:57 +0300 Subject: MDEV-17181: rocksdb.allow_to_start_after_corruption fails on current 10.2 The test needs to be run with rocksdb_flush_log_at_trx_commit=1, otherwise the changes do not survive a crash. --- .../mysql-test/rocksdb/t/allow_to_start_after_corruption-master.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption-master.opt diff --git a/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption-master.opt b/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption-master.opt new file mode 100644 index 00000000000..70c120604f6 --- /dev/null +++ b/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption-master.opt @@ -0,0 +1 @@ +--rocksdb_flush_log_at_trx_commit=1 -- cgit v1.2.1 From 940f0c78a4c45536ddede5aaeeebcf36bda53251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 10 Oct 2018 14:10:29 +0300 Subject: MDEV-11487: Make row_ins_index_entry_set_vals() static --- storage/innobase/include/row0ins.h | 10 ---------- storage/innobase/row/row0ins.cc | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/storage/innobase/include/row0ins.h b/storage/innobase/include/row0ins.h index b0b9ccd271b..a7320f9ed03 100644 --- a/storage/innobase/include/row0ins.h +++ b/storage/innobase/include/row0ins.h @@ -127,16 +127,6 @@ row_ins_sec_index_entry_low( /*!< in: if true, just do duplicate check and return. don't execute actual insert. */ MY_ATTRIBUTE((warn_unused_result)); -/** Sets the values of the dtuple fields in entry from the values of appropriate -columns in row. -@param[in] index index handler -@param[out] entry index entry to make -@param[in] row row */ -dberr_t -row_ins_index_entry_set_vals( - const dict_index_t* index, - dtuple_t* entry, - const dtuple_t* row); /***************************************************************//** Inserts an entry into a clustered index. Tries first optimistic, diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 39c219ee067..4423ec90dff 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -3330,8 +3330,8 @@ columns in row. @param[in] index index handler @param[out] entry index entry to make @param[in] row row - @return DB_SUCCESS if the set is successful */ +static dberr_t row_ins_index_entry_set_vals( const dict_index_t* index, -- cgit v1.2.1 From 3448ceb02a00f4784d41e3074fb3508d8a79ae48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 10 Oct 2018 19:19:29 +0300 Subject: 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. --- .../suite/gcol/t/innodb_virtual_debug_purge.opt | 1 + .../suite/innodb/include/innodb_wl6501_crash.inc | 416 +++++++ .../innodb/include/innodb_wl6501_crash_temp.inc | 98 ++ .../suite/innodb/include/truncate_recover.inc | 8 + mysql-test/suite/innodb/r/truncate_debug.result | 88 ++ mysql-test/suite/innodb/r/truncate_inject.result | 114 ++ .../suite/innodb/r/truncate_purge_debug.result | 29 + mysql-test/suite/innodb/r/truncate_restart.result | 12 + mysql-test/suite/innodb/t/alter_copy.opt | 1 + mysql-test/suite/innodb/t/alter_crash.opt | 1 + .../suite/innodb/t/drop_table_background.opt | 1 + mysql-test/suite/innodb/t/rename_table_debug.opt | 1 + mysql-test/suite/innodb/t/truncate.opt | 1 + mysql-test/suite/innodb/t/truncate_crash.opt | 1 + mysql-test/suite/innodb/t/truncate_debug.test | 127 ++ mysql-test/suite/innodb/t/truncate_foreign.opt | 1 + mysql-test/suite/innodb/t/truncate_inject.test | 97 ++ mysql-test/suite/innodb/t/truncate_missing.opt | 1 + mysql-test/suite/innodb/t/truncate_purge_debug.opt | 3 + .../suite/innodb/t/truncate_purge_debug.test | 49 + mysql-test/suite/innodb/t/truncate_restart.test | 16 + .../innodb_zip/include/innodb_wl6501_scale.inc | 112 ++ mysql-test/suite/innodb_zip/r/wl6501_1.result | 1202 +++++++++++++++++++ .../suite/innodb_zip/r/wl6501_crash_3.result | 462 ++++++++ .../suite/innodb_zip/r/wl6501_crash_4.result | 519 +++++++++ .../suite/innodb_zip/r/wl6501_crash_5.result | 462 ++++++++ .../suite/innodb_zip/r/wl6501_scale_1.result | 345 ++++++ mysql-test/suite/innodb_zip/t/restart.opt | 1 + mysql-test/suite/innodb_zip/t/wl6501_1.test | 451 ++++++++ mysql-test/suite/innodb_zip/t/wl6501_crash_3.test | 25 + mysql-test/suite/innodb_zip/t/wl6501_crash_4.test | 27 + mysql-test/suite/innodb_zip/t/wl6501_crash_5.test | 25 + mysql-test/suite/innodb_zip/t/wl6501_scale_1.test | 37 + .../suite/mariabackup/truncate_during_backup.opt | 1 + mysql-test/suite/sys_vars/r/sysvars_innodb.result | 14 + storage/innobase/dict/dict0crea.cc | 67 ++ storage/innobase/fil/fil0fil.cc | 150 +++ storage/innobase/fsp/fsp0fsp.cc | 1 + storage/innobase/handler/ha_innodb.cc | 37 + storage/innobase/include/dict0crea.h | 8 + storage/innobase/include/fil0fil.h | 31 + storage/innobase/include/log0log.h | 4 +- storage/innobase/include/row0trunc.h | 5 + storage/innobase/include/srv0srv.h | 3 + storage/innobase/log/log0log.cc | 20 +- storage/innobase/log/log0recv.cc | 13 +- storage/innobase/row/row0ins.cc | 3 +- storage/innobase/row/row0mysql.cc | 2 +- storage/innobase/row/row0trunc.cc | 1216 +++++++++++++++++++- storage/innobase/row/row0upd.cc | 28 + storage/innobase/srv/srv0srv.cc | 3 + storage/innobase/srv/srv0start.cc | 32 +- storage/innobase/trx/trx0rec.cc | 1 + 53 files changed, 6346 insertions(+), 27 deletions(-) create mode 100644 mysql-test/suite/gcol/t/innodb_virtual_debug_purge.opt create mode 100644 mysql-test/suite/innodb/include/innodb_wl6501_crash.inc create mode 100644 mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc create mode 100644 mysql-test/suite/innodb/include/truncate_recover.inc create mode 100644 mysql-test/suite/innodb/r/truncate_debug.result create mode 100644 mysql-test/suite/innodb/r/truncate_inject.result create mode 100644 mysql-test/suite/innodb/r/truncate_purge_debug.result create mode 100644 mysql-test/suite/innodb/r/truncate_restart.result create mode 100644 mysql-test/suite/innodb/t/alter_copy.opt create mode 100644 mysql-test/suite/innodb/t/drop_table_background.opt create mode 100644 mysql-test/suite/innodb/t/rename_table_debug.opt create mode 100644 mysql-test/suite/innodb/t/truncate.opt create mode 100644 mysql-test/suite/innodb/t/truncate_crash.opt create mode 100644 mysql-test/suite/innodb/t/truncate_debug.test create mode 100644 mysql-test/suite/innodb/t/truncate_foreign.opt create mode 100644 mysql-test/suite/innodb/t/truncate_inject.test create mode 100644 mysql-test/suite/innodb/t/truncate_missing.opt create mode 100644 mysql-test/suite/innodb/t/truncate_purge_debug.opt create mode 100644 mysql-test/suite/innodb/t/truncate_purge_debug.test create mode 100644 mysql-test/suite/innodb/t/truncate_restart.test create mode 100644 mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc create mode 100644 mysql-test/suite/innodb_zip/r/wl6501_1.result create mode 100644 mysql-test/suite/innodb_zip/r/wl6501_crash_3.result create mode 100644 mysql-test/suite/innodb_zip/r/wl6501_crash_4.result create mode 100644 mysql-test/suite/innodb_zip/r/wl6501_crash_5.result create mode 100644 mysql-test/suite/innodb_zip/r/wl6501_scale_1.result create mode 100644 mysql-test/suite/innodb_zip/t/wl6501_1.test create mode 100644 mysql-test/suite/innodb_zip/t/wl6501_crash_3.test create mode 100644 mysql-test/suite/innodb_zip/t/wl6501_crash_4.test create mode 100644 mysql-test/suite/innodb_zip/t/wl6501_crash_5.test create mode 100644 mysql-test/suite/innodb_zip/t/wl6501_scale_1.test create mode 100644 mysql-test/suite/mariabackup/truncate_during_backup.opt diff --git a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.opt b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.opt new file mode 100644 index 00000000000..20a4e60b8ec --- /dev/null +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.opt @@ -0,0 +1 @@ +--skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/include/innodb_wl6501_crash.inc b/mysql-test/suite/innodb/include/innodb_wl6501_crash.inc new file mode 100644 index 00000000000..93eca7ec060 --- /dev/null +++ b/mysql-test/suite/innodb/include/innodb_wl6501_crash.inc @@ -0,0 +1,416 @@ +# +# WL#6501: make truncate table atomic +# + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +# suppress expected warnings. +call mtr.add_suppression("The file '.*' already exists though the corresponding table did not exist in the InnoDB data dictionary"); +call mtr.add_suppression("Cannot create file '.*'"); +call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'"); + +################################################################################ +# +# Will test following scenarios: +# 1. Hit crash point while writing redo log. +# 2. Hit crash point on completion of redo log write. +# 3. Hit crash point while dropping indexes. +# 4. Hit crash point on completing drop of all indexes before creation of index +# is commenced. +# 5. Hit crash point while creating indexes. +# 6. Hit crash point after data is updated to system-table and in-memory dict. +# 7. Hit crash point before/after log checkpoint is done. +# +################################################################################ + +#----------------------------------------------------------------------------- +# +# create test-bed +# +let $per_table = `select @@innodb_file_per_table`; + +eval set global innodb_file_per_table = on; +let $WL6501_TMP_DIR = `select @@tmpdir`; +let $WL6501_DATA_DIR = `select @@datadir`; +let SEARCH_FILE = $MYSQLTEST_VARDIR/log/my_restart.err; + +#----------------------------------------------------------------------------- +# +# 1. Hit crash point while writing redo log. +# +--echo "1. Hit crash point while writing redo log." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine=innodb row_format=$wl6501_row_fmt + key_block_size=$wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_while_writing_redo_log"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 2. Hit crash point on completion of redo log write. +# +--echo "2. Hit crash point on completion of redo log write." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 3. Hit crash point while dropping indexes. +# +--echo "3. Hit crash point while dropping indexes." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_drop_of_clust_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; +# +# +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_drop_of_uniq_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +# +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; +# +# +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_drop_of_sec_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 4. Hit crash point on completing drop of all indexes before creation of index +# is commenced. +# +--echo "4. Hit crash point on completing drop of all indexes before creation" +--echo " of index is commenced." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 5. Hit crash point while creating indexes. +# +--echo "5. Hit crash point while creating indexes." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_create_of_clust_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; +# +# +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_create_of_uniq_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; +# +# +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_create_of_sec_index"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 6. Hit crash point after data is updated to system-table and in-memory dict. +# +--echo "6. Hit crash point after data is updated to system-table and" +--echo " in-memory dict." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + +#----------------------------------------------------------------------------- +# +# 7. Hit crash point before/after log checkpoint is done. +# +--echo "7. Hit crash point before/after log checkpoint is done." +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_before_log_removal"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t where f < 2.5; +drop table t; +# +# +use test; +eval set global innodb_file_per_table = $wl6501_file_per_table; +SET innodb_strict_mode=OFF; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_after_truncate_done"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; +select * from t; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +select * from t where f < 2.5; +drop table t; + + +#----------------------------------------------------------------------------- +# +# remove test-bed +# +eval set global innodb_file_per_table = $per_table; diff --git a/mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc b/mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc new file mode 100644 index 00000000000..edec93b875c --- /dev/null +++ b/mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc @@ -0,0 +1,98 @@ +# +# WL#6501: make truncate table atomic +# + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +# suppress expected warnings +call mtr.add_suppression("does not exist in the InnoDB internal"); + +################################################################################ +# +# Will test following scenarios: +# 1. Hit crash point on completing drop of all indexes before creation of index +# is commenced. +# 2. Hit crash point after data is updated to system-table and in-memory dict. +# +################################################################################ + +#----------------------------------------------------------------------------- +# +# create test-bed +# +let $per_table = `select @@innodb_file_per_table`; + +eval set global innodb_file_per_table = on; +let $WL6501_TMP_DIR = `select @@tmpdir`; +let $WL6501_DATA_DIR = `select @@datadir`; +let SEARCH_FILE = $MYSQLTEST_VARDIR/log/my_restart.err; + +#----------------------------------------------------------------------------- +# +# 1. Hit crash point on completing drop of all indexes before creation of index +# is commenced. +# +--echo "1. Hit crash point on completing drop of all indexes before creation" +--echo " of index is commenced." +eval set global innodb_file_per_table = $wl6501_file_per_table; +set innodb_strict_mode=off; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; + +#----------------------------------------------------------------------------- +# +# 2. Hit crash point after data is updated to system-table and in-memory dict. +# +--echo "2. Hit crash point after data is updated to system-table and" +--echo " in-memory dict." +eval set global innodb_file_per_table = $wl6501_file_per_table; +set innodb_strict_mode=off; +--disable_warnings +eval create $wl6501_temp table t ( + i int, f float, c char, + primary key pk(i), unique findex(f), index ck(c)) + engine = innodb row_format = $wl6501_row_fmt + key_block_size = $wl6501_kbs; +--enable_warnings +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +check table t; +# +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +--source include/expect_crash.inc +--error 2013 +truncate table t; +# +--source include/start_mysqld.inc +check table t; + +#----------------------------------------------------------------------------- +# +# remove test-bed +# +eval set global innodb_file_per_table = $per_table; diff --git a/mysql-test/suite/innodb/include/truncate_recover.inc b/mysql-test/suite/innodb/include/truncate_recover.inc new file mode 100644 index 00000000000..fe068afa6e3 --- /dev/null +++ b/mysql-test/suite/innodb/include/truncate_recover.inc @@ -0,0 +1,8 @@ +begin; +update t1 set c = 'MariaDB'; +update t1 set c = 'InnoDB'; +eval set global debug_dbug = '+d,$SEARCH_PATTERN'; +commit; +--source include/shutdown_mysqld.inc +--source include/search_pattern_in_file.inc +--source include/start_mysqld.inc diff --git a/mysql-test/suite/innodb/r/truncate_debug.result b/mysql-test/suite/innodb/r/truncate_debug.result new file mode 100644 index 00000000000..c04b83dbbe8 --- /dev/null +++ b/mysql-test/suite/innodb/r/truncate_debug.result @@ -0,0 +1,88 @@ +# +# Bug #23070734 CONCURRENT TRUNCATE TABLES CAUSE STALLS +# +SET @ahi= @@global.innodb_adaptive_hash_index; +SET GLOBAL innodb_adaptive_hash_index=OFF; +SET GLOBAL innodb_adaptive_hash_index=ON; +Test_1 :- Check if DDL operations are possible on +table being truncated. Also check if +DDL operations on other tables succeed. +create table t1 (f1 int,f2 int,key(f2),f3 int) engine=innodb; +create index idx1 on t1(f3); +create table t2 (f1 int,f2 int,key(f2),f3 int) engine=innodb; +create table t3 (f1 int,f2 int,key(f2)) engine=innodb; +insert into t1 values (10,20,30),(30,40,50),(50,60,70); +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t2 values (10,20,30),(30,40,50),(50,60,70); +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t3 values (10,20),(30,40),(50,50); +insert into t3 select * from t3; +insert into t3 select * from t3; +SET session lock_wait_timeout = 1; +connect con1,localhost,root,,; +SET DEBUG_SYNC= 'buffer_pool_scan SIGNAL started WAIT_FOR finish_scan'; +truncate table t1; +connection default; +SET DEBUG_SYNC= 'now WAIT_FOR started'; +Check Analyze table. Gives lock time out error. +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze Error Lock wait timeout exceeded; try restarting transaction +test.t1 analyze status Operation failed +Check if we can turn off auto recalculation. +alter table t1 STATS_AUTO_RECALC=0; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check if we can turn off persistent stats on the table +alter table t1 STATS_PERSISTENT=0; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check if DML is possible on table being truncated +insert into t1 values (10,89,99); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check if DDL is possible on table being truncated +alter table t1 add column f4 int; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +check if table can be created with the same name +create table t1 (bd int) engine=innodb; +Got one of the listed errors +check if index can be created on table being truncated +create index idx1 on t1(f1); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check if DROP of table is possible during truncate +drop table t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check if select is possible during truncate +select * from t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t2 where t2.f1=t1.f1; +ERROR 42S22: Unknown column 't1.f1' in 'where clause' +Check concurrent truncate operation on table; +truncate table t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +Check concurrent selects and inserts on the other table +insert into t3 values (10,20),(30,40),(50,50); +select * from t3 where f1=40; +f1 f2 +Concurrent truncate on other tables +truncate table t2; +Concurrent alters on the other tables +alter table t2 add column f4 int; +check if index can be created on the other table +create index idx1 on t2(f3); +Check if we can turn off persistent stats off entire instance +SET GLOBAL innodb_stats_persistent=off; +connect con2,localhost,root,,; +set global innodb_adaptive_hash_index=off; +connection default; +SET DEBUG_SYNC= 'now SIGNAL finish_scan'; +connection con1; +disconnect con1; +connection con2; +disconnect con2; +connection default; +SET DEBUG_SYNC= 'RESET'; +SET GLOBAL innodb_adaptive_hash_index=@ahi; +drop table t1,t2,t3; diff --git a/mysql-test/suite/innodb/r/truncate_inject.result b/mysql-test/suite/innodb/r/truncate_inject.result new file mode 100644 index 00000000000..5ec532a0f83 --- /dev/null +++ b/mysql-test/suite/innodb/r/truncate_inject.result @@ -0,0 +1,114 @@ +SET @save_dbug = @@SESSION.debug_dbug; +call mtr.add_suppression("InnoDB: Flagged corruption of .* in table `test`\\.`t` in TRUNCATE TABLE"); +# 1. Error in assigning undo logs for truncate action +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; +Table Op Msg_type Msg_text +test.t check status OK +SET debug_dbug = '+d,ib_err_trunc_assigning_undo_log'; +truncate table t; +ERROR HY000: Got error 168 "Unknown (generic) error from engine" from storage engine InnoDB +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +# 2. Error while preparing for truncate +SET debug_dbug = '+d,ib_err_trunc_preparing_for_truncate'; +truncate table t; +ERROR HY000: Got error 168 "Unknown (generic) error from engine" from storage engine InnoDB +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +# 3. Error while dropping/creating indexes +SET debug_dbug = '+d,ib_err_trunc_drop_index'; +truncate table t; +ERROR HY000: Got error 168 "Unknown (generic) error from engine" from storage engine InnoDB +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check Warning InnoDB: Index PRIMARY is marked as corrupted +test.t check error Corrupt +select * from t; +Got one of the listed errors +drop table t; +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; +Table Op Msg_type Msg_text +test.t check status OK +SET debug_dbug = '+d,ib_err_trunc_create_index'; +truncate table t; +ERROR HY000: Got error 168 "Unknown (generic) error from engine" from storage engine InnoDB +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check Warning InnoDB: Index PRIMARY is marked as corrupted +test.t check error Corrupt +select * from t; +Got one of the listed errors +drop table t; +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; +Table Op Msg_type Msg_text +test.t check status OK +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +drop table t; +# 4. Error while completing truncate of table involving FTS +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), +FULLTEXT INDEX(c)) ENGINE = InnoDB; +insert into t values (1, 1.1, 'mysql is now oracle company'), +(2, 2.2, 'innodb is part of mysql'), +(3, 3.3, 'innodb is default storage engine of mysql'); +check table t; +Table Op Msg_type Msg_text +test.t check status OK +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +drop table t; +# 5. Error while updating sys-tables +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), +FULLTEXT INDEX(c)) ENGINE = InnoDB; +insert into t values (1, 1.1, 'mysql is now oracle company'), +(2, 2.2, 'innodb is part of mysql'), +(3, 3.3, 'innodb is default storage engine of mysql'); +check table t; +Table Op Msg_type Msg_text +test.t check status OK +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t order by i; +i f c +drop table t; diff --git a/mysql-test/suite/innodb/r/truncate_purge_debug.result b/mysql-test/suite/innodb/r/truncate_purge_debug.result new file mode 100644 index 00000000000..164987083d5 --- /dev/null +++ b/mysql-test/suite/innodb/r/truncate_purge_debug.result @@ -0,0 +1,29 @@ +# +# Bug #23070734 CONCURRENT TRUNCATE TABLES CAUSE STALLS +# +create table t1 (f1 int ,f2 int,key(f2)) engine=innodb; +begin; +insert into t1 values (10,45),(20,78),(30,88),(40,23),(50,78),(60,11),(70,56),(80,90); +delete from t1; +connect con2,localhost,root,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +commit; +connect con1,localhost,root,,; +SET DEBUG_SYNC= 'buffer_pool_scan SIGNAL started WAIT_FOR finish_scan'; +truncate table t1; +connection con2; +SET DEBUG_SYNC= 'now WAIT_FOR started'; +COMMIT; +disconnect con2; +connection default; +InnoDB 0 transactions not purged +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; +SET DEBUG_SYNC = 'now SIGNAL finish_scan'; +connection con1; +disconnect con1; +connection default; +SET DEBUG_SYNC = 'RESET'; +drop table t1; diff --git a/mysql-test/suite/innodb/r/truncate_restart.result b/mysql-test/suite/innodb/r/truncate_restart.result new file mode 100644 index 00000000000..b6d14124371 --- /dev/null +++ b/mysql-test/suite/innodb/r/truncate_restart.result @@ -0,0 +1,12 @@ +SET GLOBAL innodb_stats_persistent= ON; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB STATS_PERSISTENT=1; +connect con1,localhost,root,,test; +SET DEBUG_SYNC='ib_trunc_table_trunc_completing SIGNAL committed WAIT_FOR ever'; +TRUNCATE TABLE t1; +connection default; +SET DEBUG_SYNC='now WAIT_FOR committed'; +disconnect con1; +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/alter_copy.opt b/mysql-test/suite/innodb/t/alter_copy.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/alter_copy.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/alter_crash.opt b/mysql-test/suite/innodb/t/alter_crash.opt index 39b93371503..96710441921 100644 --- a/mysql-test/suite/innodb/t/alter_crash.opt +++ b/mysql-test/suite/innodb/t/alter_crash.opt @@ -1 +1,2 @@ --loose-innodb-sys-tables +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/drop_table_background.opt b/mysql-test/suite/innodb/t/drop_table_background.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/drop_table_background.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/rename_table_debug.opt b/mysql-test/suite/innodb/t/rename_table_debug.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/rename_table_debug.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/truncate.opt b/mysql-test/suite/innodb/t/truncate.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/truncate_crash.opt b/mysql-test/suite/innodb/t/truncate_crash.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_crash.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/truncate_debug.test b/mysql-test/suite/innodb/t/truncate_debug.test new file mode 100644 index 00000000000..5fee9174d98 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_debug.test @@ -0,0 +1,127 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--source include/count_sessions.inc + +--echo # +--echo # Bug #23070734 CONCURRENT TRUNCATE TABLES CAUSE STALLS +--echo # + +SET @ahi= @@global.innodb_adaptive_hash_index; +# Ensure that there is no adaptive hash index on any system tables, +# or any other tables than the ones that we are creating below. +SET GLOBAL innodb_adaptive_hash_index=OFF; +SET GLOBAL innodb_adaptive_hash_index=ON; + +--echo Test_1 :- Check if DDL operations are possible on +--echo table being truncated. Also check if +--echo DDL operations on other tables succeed. + +create table t1 (f1 int,f2 int,key(f2),f3 int) engine=innodb; +create index idx1 on t1(f3); +create table t2 (f1 int,f2 int,key(f2),f3 int) engine=innodb; +create table t3 (f1 int,f2 int,key(f2)) engine=innodb; + +insert into t1 values (10,20,30),(30,40,50),(50,60,70); +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t1 select * from t1; +insert into t2 values (10,20,30),(30,40,50),(50,60,70); + +insert into t2 select * from t2; +insert into t2 select * from t2; +insert into t2 select * from t2; + +insert into t3 values (10,20),(30,40),(50,50); +insert into t3 select * from t3; +insert into t3 select * from t3; + +SET session lock_wait_timeout = 1; + +connect (con1,localhost,root,,); +SET DEBUG_SYNC= 'buffer_pool_scan SIGNAL started WAIT_FOR finish_scan'; +send truncate table t1; + +connection default; +SET DEBUG_SYNC= 'now WAIT_FOR started'; + +--echo Check Analyze table. Gives lock time out error. +analyze table t1; + +--echo Check if we can turn off auto recalculation. +--error ER_LOCK_WAIT_TIMEOUT +alter table t1 STATS_AUTO_RECALC=0; + +--echo Check if we can turn off persistent stats on the table +--error ER_LOCK_WAIT_TIMEOUT +alter table t1 STATS_PERSISTENT=0; + +--echo Check if DML is possible on table being truncated +--error ER_LOCK_WAIT_TIMEOUT +insert into t1 values (10,89,99); + +--echo Check if DDL is possible on table being truncated +--error ER_LOCK_WAIT_TIMEOUT +alter table t1 add column f4 int; + +--echo check if table can be created with the same name +--error ER_TABLE_EXISTS_ERROR,ER_LOCK_WAIT_TIMEOUT +create table t1 (bd int) engine=innodb; + +--echo check if index can be created on table being truncated +--error ER_LOCK_WAIT_TIMEOUT +create index idx1 on t1(f1); + +--echo Check if DROP of table is possible during truncate +--error ER_LOCK_WAIT_TIMEOUT +drop table t1; + +--echo Check if select is possible during truncate +--error ER_LOCK_WAIT_TIMEOUT +select * from t1; + +--error ER_BAD_FIELD_ERROR +select * from t2 where t2.f1=t1.f1; + +--echo Check concurrent truncate operation on table; +--error ER_LOCK_WAIT_TIMEOUT +truncate table t1; + +--echo Check concurrent selects and inserts on the other table +insert into t3 values (10,20),(30,40),(50,50); +select * from t3 where f1=40; + +--echo Concurrent truncate on other tables +truncate table t2; + +--echo Concurrent alters on the other tables +alter table t2 add column f4 int; + +--echo check if index can be created on the other table +create index idx1 on t2(f3); + +--echo Check if we can turn off persistent stats off entire instance +SET GLOBAL innodb_stats_persistent=off; + +connect (con2,localhost,root,,); +send set global innodb_adaptive_hash_index=off; + +connection default; +SET DEBUG_SYNC= 'now SIGNAL finish_scan'; + +connection con1; +reap; +disconnect con1; + +connection con2; +reap; +disconnect con2; + +connection default; +SET DEBUG_SYNC= 'RESET'; + +SET GLOBAL innodb_adaptive_hash_index=@ahi; + +drop table t1,t2,t3; +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/truncate_foreign.opt b/mysql-test/suite/innodb/t/truncate_foreign.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_foreign.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/truncate_inject.test b/mysql-test/suite/innodb/t/truncate_inject.test new file mode 100644 index 00000000000..35e516324bb --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_inject.test @@ -0,0 +1,97 @@ +# This test is based on innodb_zip.wl6501_error_1 in MySQL 5.7. + +--source include/have_innodb.inc +--source include/innodb_row_format.inc +--source include/have_debug.inc + +SET @save_dbug = @@SESSION.debug_dbug; + +call mtr.add_suppression("InnoDB: Flagged corruption of .* in table `test`\\.`t` in TRUNCATE TABLE"); + +--echo # 1. Error in assigning undo logs for truncate action +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; +# +SET debug_dbug = '+d,ib_err_trunc_assigning_undo_log'; +--error ER_GET_ERRNO +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +select * from t; + +--echo # 2. Error while preparing for truncate +SET debug_dbug = '+d,ib_err_trunc_preparing_for_truncate'; +--error ER_GET_ERRNO +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +select * from t; + +--echo # 3. Error while dropping/creating indexes +SET debug_dbug = '+d,ib_err_trunc_drop_index'; +--error ER_GET_ERRNO +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +--error ER_TABLE_CORRUPT,ER_GET_ERRNO +select * from t; +drop table t; + +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; + +SET debug_dbug = '+d,ib_err_trunc_create_index'; +--error ER_GET_ERRNO +truncate table t; +SET debug_dbug = @save_dbug; +check table t; +--error ER_TABLE_CORRUPT,ER_GET_ERRNO +select * from t; +drop table t; + +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), INDEX ck(c)) +ENGINE = InnoDB; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +check table t; + +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; + +check table t; +select * from t; +drop table t; + +--echo # 4. Error while completing truncate of table involving FTS +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), +FULLTEXT INDEX(c)) ENGINE = InnoDB; +insert into t values (1, 1.1, 'mysql is now oracle company'), + (2, 2.2, 'innodb is part of mysql'), + (3, 3.3, 'innodb is default storage engine of mysql'); +check table t; +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; + +check table t; +select * from t; +drop table t; + +--echo # 5. Error while updating sys-tables +CREATE TABLE t (i int PRIMARY KEY, f float UNIQUE, c char(100), +FULLTEXT INDEX(c)) ENGINE = InnoDB; +insert into t values (1, 1.1, 'mysql is now oracle company'), + (2, 2.2, 'innodb is part of mysql'), + (3, 3.3, 'innodb is default storage engine of mysql'); +check table t; +SET debug_dbug = '+d,ib_err_trunc_temp_recreate_index'; +truncate table t; +SET debug_dbug = @save_dbug; + +check table t; +select * from t order by i; +drop table t; diff --git a/mysql-test/suite/innodb/t/truncate_missing.opt b/mysql-test/suite/innodb/t/truncate_missing.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_missing.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb/t/truncate_purge_debug.opt b/mysql-test/suite/innodb/t/truncate_purge_debug.opt new file mode 100644 index 00000000000..8bed7e46166 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_purge_debug.opt @@ -0,0 +1,3 @@ +--innodb-purge-threads=1 +--innodb-purge-batch-size=1 +--innodb-stats-persistent=OFF diff --git a/mysql-test/suite/innodb/t/truncate_purge_debug.test b/mysql-test/suite/innodb/t/truncate_purge_debug.test new file mode 100644 index 00000000000..e8f5768f557 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_purge_debug.test @@ -0,0 +1,49 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/count_sessions.inc + +--echo # +--echo # Bug #23070734 CONCURRENT TRUNCATE TABLES CAUSE STALLS +--echo # + +create table t1 (f1 int ,f2 int,key(f2)) engine=innodb; +begin; +insert into t1 values (10,45),(20,78),(30,88),(40,23),(50,78),(60,11),(70,56),(80,90); +delete from t1; + +connect (con2,localhost,root,,); +# Stop the purge thread +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +# Ensure that the history list length will actually be decremented by purge. +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +commit; + +connect (con1,localhost,root,,); +SET DEBUG_SYNC= 'buffer_pool_scan SIGNAL started WAIT_FOR finish_scan'; +send truncate table t1; + +connection con2; +SET DEBUG_SYNC= 'now WAIT_FOR started'; +# Allow purge to proceed, by discarding our read view. +COMMIT; +disconnect con2; + +connection default; +--source include/wait_all_purged.inc + +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; + +SET DEBUG_SYNC = 'now SIGNAL finish_scan'; + +connection con1; +reap; +disconnect con1; + +connection default; +SET DEBUG_SYNC = 'RESET'; +drop table t1; +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/truncate_restart.test b/mysql-test/suite/innodb/t/truncate_restart.test new file mode 100644 index 00000000000..60a3d83cd81 --- /dev/null +++ b/mysql-test/suite/innodb/t/truncate_restart.test @@ -0,0 +1,16 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +SET GLOBAL innodb_stats_persistent= ON; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB STATS_PERSISTENT=1; +--connect (con1,localhost,root,,test) +SET DEBUG_SYNC='ib_trunc_table_trunc_completing SIGNAL committed WAIT_FOR ever'; +--send +TRUNCATE TABLE t1; +--connection default +SET DEBUG_SYNC='now WAIT_FOR committed'; +--source include/restart_mysqld.inc +--disconnect con1 +SELECT COUNT(*) FROM t1; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc b/mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc new file mode 100644 index 00000000000..bef28a9c484 --- /dev/null +++ b/mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc @@ -0,0 +1,112 @@ +# +# load tables with some significant amount of data and then truncate it. +# + +#----------------------------------------------------------------------------- +# +# create test-bed +# +let $per_table = `select @@innodb_file_per_table`; +let $format = `select @@innodb_file_format`; + +let $WL6501_TMP_DIR = `select @@tmpdir`; +let $WL6501_DATA_DIR = `select @@datadir`; +set innodb_strict_mode=OFF; + +#----------------------------------------------------------------------------- +# +# create procedure to load data +# +delimiter |; +create procedure populate() +begin + declare i int default 1; + while (i <= 5000) do + insert into t1 values (i, 'a', 'b'); + insert into t2 values (i, 'a', 'b'); + insert into t3 values (i, 'a', 'b'); + set i = i + 1; + end while; +end| +create procedure populate_small() +begin + declare i int default 10001; + while (i <= 12000) do + insert into t1 values (i, 'c', 'd'); + insert into t2 values (i, 'a', 'b'); + insert into t3 values (i, 'a', 'b'); + set i = i + 1; + end while; +end| +delimiter ;| + +#----------------------------------------------------------------------------- +# +# create and load the tables. +# +eval set global innodb_file_per_table = $wl6501_file_per_table; +--replace_regex /[0-9]+/NUMBER/ +eval create table t1 + (i int, c1 char(100), c2 char(100), + index c1_idx(c1)) + engine=innodb row_format=$wl6501_row_fmt + key_block_size=$wl6501_kbs; +eval create table t2 + (i int, c1 char(100), c2 char(100), + index c1_idx(c1)) + engine=innodb row_format=$wl6501_row_fmt + key_block_size=$wl6501_kbs; +eval create temporary table t3 + (i int, c1 char(100), c2 char(100), + index c1_idx(c1)) + engine=innodb row_format=$wl6501_row_fmt + key_block_size=$wl6501_kbs; +# +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +begin; +call populate(); +commit; +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +# +truncate table t1; +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +# +call populate_small(); +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +# +truncate table t2; +truncate table t3; +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +# +call populate_small(); +select count(*) from t1; +select count(*) from t2; +select count(*) from t3; +# +drop table t1; +drop table t2; +drop table t3; + +#----------------------------------------------------------------------------- +# +# drop the procedure +# +drop procedure populate; +drop procedure populate_small; + +#----------------------------------------------------------------------------- +# +# remove test-bed +# +eval set global innodb_file_format = $format; +eval set global innodb_file_per_table = $per_table; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_1.result b/mysql-test/suite/innodb_zip/r/wl6501_1.result new file mode 100644 index 00000000000..bf901804be5 --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/wl6501_1.result @@ -0,0 +1,1202 @@ +set global innodb_file_per_table=on; +# Verify that 'TRUNCATE TABLE' statement works fine and the size +# of .ibd file is equal to the initial size after truncation. +drop table if exists t1,t2,t3,t4,t6; +Warnings: +Note 1051 Unknown table 'test.t1' +Note 1051 Unknown table 'test.t2' +Note 1051 Unknown table 'test.t3' +Note 1051 Unknown table 'test.t4' +Note 1051 Unknown table 'test.t6' +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_during_drop_index_temp_table"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_during_drop_index_temp_table point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t5; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_drop_of_sec_index point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_drop_of_sec_index point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_drop_of_sec_index point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_drop_of_sec_index point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_drop_reinit_done_create_to_start---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t5; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_create_of_sec_index---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_create_of_sec_index---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_create_of_sec_index---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_on_create_of_sec_index---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_before_log_removal point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_before_log_removal point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_before_log_removal point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_before_log_removal point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_truncate_done point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; +create table t1(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=redundant; +create table t2(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compact; +create table t3(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=compressed key_block_size=4; +create table t4(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb row_format=dynamic; +create temporary table t5(c1 int not null, +c2 int not null, +c3 char(255) not null, +c4 text(500) not null, +c5 blob(500) not null, +c6 varchar(500) not null, +c7 varchar(500) not null, +c8 datetime, +c9 decimal(5,3), +primary key (c1), +index (c3,c4(50),c5(50)), +index (c2)) +engine=innodb; +create table t6 ( a int ) engine = innodb; +insert into t6 values (50),(100),(150); +select count(*) from t1; +count(*) +3 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +count(*) +3 +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_redo_log_write_complete point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +3 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_redo_log_write_complete point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t2; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +3 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_redo_log_write_complete point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t3; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +3 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +"---debug ib_trunc_crash_after_redo_log_write_complete point---" +# Write file to make mysql-test-run.pl expect crash and restart +# Run the crashing query +truncate table t4; +ERROR HY000: Lost connection to MySQL server during query +# Restart the MySQL server +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +select count(*) from t4; +count(*) +0 +select count(*) from t5; +ERROR 42S02: Table 'test.t5' doesn't exist +select count(*) from t6; +count(*) +3 +drop table t1, t2, t3, t4, t6; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_crash_3.result b/mysql-test/suite/innodb_zip/r/wl6501_crash_3.result new file mode 100644 index 00000000000..554bb2892f6 --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/wl6501_crash_3.result @@ -0,0 +1,462 @@ +call mtr.add_suppression("The file '.*' already exists though the corresponding table did not exist in the InnoDB data dictionary"); +call mtr.add_suppression("Cannot create file '.*'"); +call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'"); +set global innodb_file_per_table = on; +"1. Hit crash point while writing redo log." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine=innodb row_format=compressed +key_block_size=16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_while_writing_redo_log"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"2. Hit crash point on completion of redo log write." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"3. Hit crash point while dropping indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"4. Hit crash point on completing drop of all indexes before creation" +" of index is commenced." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"5. Hit crash point while creating indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"6. Hit crash point after data is updated to system-table and" +" in-memory dict." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"7. Hit crash point before/after log checkpoint is done." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 16; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_crash_4.result b/mysql-test/suite/innodb_zip/r/wl6501_crash_4.result new file mode 100644 index 00000000000..d766ecceaac --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/wl6501_crash_4.result @@ -0,0 +1,519 @@ +call mtr.add_suppression("The file '.*' already exists though the corresponding table did not exist in the InnoDB data dictionary"); +call mtr.add_suppression("Cannot create file '.*'"); +call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'"); +set global innodb_file_per_table = on; +"1. Hit crash point while writing redo log." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine=innodb row_format=compressed +key_block_size=4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_while_writing_redo_log"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"2. Hit crash point on completion of redo log write." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"3. Hit crash point while dropping indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"4. Hit crash point on completing drop of all indexes before creation" +" of index is commenced." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"5. Hit crash point while creating indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"6. Hit crash point after data is updated to system-table and" +" in-memory dict." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"7. Hit crash point before/after log checkpoint is done." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +set global innodb_file_per_table = 1; +call mtr.add_suppression("does not exist in the InnoDB internal"); +set global innodb_file_per_table = on; +"1. Hit crash point on completing drop of all indexes before creation" +" of index is commenced." +set global innodb_file_per_table = 1; +set innodb_strict_mode=off; +create temporary table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check Error Table 'test.t' doesn't exist +test.t check status Operation failed +"2. Hit crash point after data is updated to system-table and" +" in-memory dict." +set global innodb_file_per_table = 1; +set innodb_strict_mode=off; +create temporary table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 4; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check Error Table 'test.t' doesn't exist +test.t check status Operation failed +set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_crash_5.result b/mysql-test/suite/innodb_zip/r/wl6501_crash_5.result new file mode 100644 index 00000000000..b5fea6382ff --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/wl6501_crash_5.result @@ -0,0 +1,462 @@ +call mtr.add_suppression("The file '.*' already exists though the corresponding table did not exist in the InnoDB data dictionary"); +call mtr.add_suppression("Cannot create file '.*'"); +call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'"); +set global innodb_file_per_table = on; +"1. Hit crash point while writing redo log." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine=innodb row_format=compressed +key_block_size=8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_while_writing_redo_log"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"2. Hit crash point on completion of redo log write." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"3. Hit crash point while dropping indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"4. Hit crash point on completing drop of all indexes before creation" +" of index is commenced." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"5. Hit crash point while creating indexes." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"6. Hit crash point after data is updated to system-table and" +" in-memory dict." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +"7. Hit crash point before/after log checkpoint is done." +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +use test; +set global innodb_file_per_table = 1; +SET innodb_strict_mode=OFF; +create table t ( +i int, f float, c char, +primary key pk(i), unique findex(f), index ck(c)) +engine = innodb row_format = compressed +key_block_size = 8; +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +check table t; +Table Op Msg_type Msg_text +test.t check status OK +set session debug = "+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +truncate table t; +ERROR HY000: Lost connection to MySQL server during query +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +i f c +insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); +select * from t; +i f c +1 1.1 a +2 2.2 b +3 3.3 c +select * from t where f < 2.5; +i f c +1 1.1 a +2 2.2 b +drop table t; +set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result b/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result new file mode 100644 index 00000000000..3a74b6ebc11 --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result @@ -0,0 +1,345 @@ +set innodb_strict_mode=OFF; +create procedure populate() +begin +declare i int default 1; +while (i <= 5000) do +insert into t1 values (i, 'a', 'b'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +create procedure populate_small() +begin +declare i int default 10001; +while (i <= 12000) do +insert into t1 values (i, 'c', 'd'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +set global innodb_file_per_table = 1; +create table tNUMBER +(i int, cNUMBER char(NUMBER), cNUMBER char(NUMBER), +index cNUMBER_idx(cNUMBER)) +engine=innodb row_format=compact +key_block_size=NUMBER; +Warnings: +Warning NUMBER InnoDB: ignoring KEY_BLOCK_SIZE=NUMBER unless ROW_FORMAT=COMPRESSED. +create table t2 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compact +key_block_size=16; +Warnings: +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16 unless ROW_FORMAT=COMPRESSED. +create temporary table t3 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compact +key_block_size=16; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +begin; +call populate(); +commit; +select count(*) from t1; +count(*) +5000 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +truncate table t1; +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +call populate_small(); +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +7000 +select count(*) from t3; +count(*) +7000 +truncate table t2; +truncate table t3; +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +call populate_small(); +select count(*) from t1; +count(*) +4000 +select count(*) from t2; +count(*) +2000 +select count(*) from t3; +count(*) +2000 +drop table t1; +drop table t2; +drop table t3; +drop procedure populate; +drop procedure populate_small; +set global innodb_file_format = Barracuda; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See https://mariadb.com/kb/en/library/xtradbinnodb-file-format/ +set global innodb_file_per_table = 1; +set innodb_strict_mode=OFF; +create procedure populate() +begin +declare i int default 1; +while (i <= 5000) do +insert into t1 values (i, 'a', 'b'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +create procedure populate_small() +begin +declare i int default 10001; +while (i <= 12000) do +insert into t1 values (i, 'c', 'd'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +set global innodb_file_per_table = 1; +create table tNUMBER +(i int, cNUMBER char(NUMBER), cNUMBER char(NUMBER), +index cNUMBER_idx(cNUMBER)) +engine=innodb row_format=compressed +key_block_size=NUMBER; +create table t2 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compressed +key_block_size=16; +create temporary table t3 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compressed +key_block_size=16; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +begin; +call populate(); +commit; +select count(*) from t1; +count(*) +5000 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +truncate table t1; +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +call populate_small(); +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +7000 +select count(*) from t3; +count(*) +7000 +truncate table t2; +truncate table t3; +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +call populate_small(); +select count(*) from t1; +count(*) +4000 +select count(*) from t2; +count(*) +2000 +select count(*) from t3; +count(*) +2000 +drop table t1; +drop table t2; +drop table t3; +drop procedure populate; +drop procedure populate_small; +set global innodb_file_format = Barracuda; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See https://mariadb.com/kb/en/library/xtradbinnodb-file-format/ +set global innodb_file_per_table = 1; +set innodb_strict_mode=OFF; +create procedure populate() +begin +declare i int default 1; +while (i <= 5000) do +insert into t1 values (i, 'a', 'b'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +create procedure populate_small() +begin +declare i int default 10001; +while (i <= 12000) do +insert into t1 values (i, 'c', 'd'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +set global innodb_file_per_table = 0; +create table tNUMBER +(i int, cNUMBER char(NUMBER), cNUMBER char(NUMBER), +index cNUMBER_idx(cNUMBER)) +engine=innodb row_format=compact +key_block_size=NUMBER; +Warnings: +Warning NUMBER InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning NUMBER InnoDB: ignoring KEY_BLOCK_SIZE=NUMBER. +create table t2 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compact +key_block_size=16; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +create temporary table t3 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compact +key_block_size=16; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +begin; +call populate(); +commit; +select count(*) from t1; +count(*) +5000 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +truncate table t1; +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +call populate_small(); +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +7000 +select count(*) from t3; +count(*) +7000 +truncate table t2; +truncate table t3; +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +call populate_small(); +select count(*) from t1; +count(*) +4000 +select count(*) from t2; +count(*) +2000 +select count(*) from t3; +count(*) +2000 +drop table t1; +drop table t2; +drop table t3; +drop procedure populate; +drop procedure populate_small; +set global innodb_file_format = Barracuda; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See https://mariadb.com/kb/en/library/xtradbinnodb-file-format/ +set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/t/restart.opt b/mysql-test/suite/innodb_zip/t/restart.opt index 52314cbf241..fd89db6cc1d 100644 --- a/mysql-test/suite/innodb_zip/t/restart.opt +++ b/mysql-test/suite/innodb_zip/t/restart.opt @@ -1,3 +1,4 @@ --loose-innodb-sys-tables --loose-innodb-sys-tablespaces --loose-innodb-sys-datafiles +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/innodb_zip/t/wl6501_1.test b/mysql-test/suite/innodb_zip/t/wl6501_1.test new file mode 100644 index 00000000000..dd8b5f65b31 --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/wl6501_1.test @@ -0,0 +1,451 @@ + +#################################################################### +# TC to check truncate table statement atomicity for single # +# tablespace # +# Sceanrio covered: # +# 1. Debug points added for worklog # +# 2. Table with differnt row types # +# 3. Transactional statement. # +#################################################################### + + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc +--source include/have_innodb_16k.inc + +# Valgrind would result in a "long semaphore wait" inside InnoDB +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +#----------------------------------------------------------------------- +--disable_query_log +let $MYSQL_DATA_DIR= `select @@datadir`; +let $data_directory = data directory='$MYSQL_TMP_DIR/alt_dir'; +let $innodb_file_per_table_orig=`select @@innodb_file_per_table`; + +call mtr.add_suppression("InnoDB.*table did not exist in the InnoDB data dictionary.*"); +call mtr.add_suppression("InnoDB: A page in the doublewrite buffer is not within space bounds.*"); +call mtr.add_suppression("InnoDB: Cannot create file.*"); +call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'.*"); +call mtr.add_suppression("InnoDB: A page in the doublewrite buffer is not within space bounds"); +call mtr.add_suppression("InnoDB: Error: table .* does not exist in the InnoDB internal"); +--enable_query_log + +#----------------------------------------------------------------------- +set global innodb_file_per_table=on; +--echo # Verify that 'TRUNCATE TABLE' statement works fine and the size +--echo # of .ibd file is equal to the initial size after truncation. + +#----------------------------------------------------------------------- +drop table if exists t1,t2,t3,t4,t6; +let $cnt = 6; +while ($cnt) { + + # table with basic data type + primary ,secondary,composite,prefix index + create table t1(c1 int not null, + c2 int not null, + c3 char(255) not null, + c4 text(500) not null, + c5 blob(500) not null, + c6 varchar(500) not null, + c7 varchar(500) not null, + c8 datetime, + c9 decimal(5,3), + primary key (c1), + index (c3,c4(50),c5(50)), + index (c2)) + engine=innodb row_format=redundant; + + + create table t2(c1 int not null, + c2 int not null, + c3 char(255) not null, + c4 text(500) not null, + c5 blob(500) not null, + c6 varchar(500) not null, + c7 varchar(500) not null, + c8 datetime, + c9 decimal(5,3), + primary key (c1), + index (c3,c4(50),c5(50)), + index (c2)) + engine=innodb row_format=compact; + + + # with row type , key block size = 4K + create table t3(c1 int not null, + c2 int not null, + c3 char(255) not null, + c4 text(500) not null, + c5 blob(500) not null, + c6 varchar(500) not null, + c7 varchar(500) not null, + c8 datetime, + c9 decimal(5,3), + primary key (c1), + index (c3,c4(50),c5(50)), + index (c2)) + engine=innodb row_format=compressed key_block_size=4; + + + create table t4(c1 int not null, + c2 int not null, + c3 char(255) not null, + c4 text(500) not null, + c5 blob(500) not null, + c6 varchar(500) not null, + c7 varchar(500) not null, + c8 datetime, + c9 decimal(5,3), + primary key (c1), + index (c3,c4(50),c5(50)), + index (c2)) + engine=innodb row_format=dynamic; + + + create temporary table t5(c1 int not null, + c2 int not null, + c3 char(255) not null, + c4 text(500) not null, + c5 blob(500) not null, + c6 varchar(500) not null, + c7 varchar(500) not null, + c8 datetime, + c9 decimal(5,3), + primary key (c1), + index (c3,c4(50),c5(50)), + index (c2)) + engine=innodb; + + create table t6 ( a int ) engine = innodb; + insert into t6 values (50),(100),(150); + + --disable_query_log + --disable_result_log + let $n=5; + + # load created tables. + while ($n) + { + start transaction; + + eval insert ignore into t1 values( + $n, $n, + repeat(concat(' tc3_',$n), 42), + repeat(concat(' tc4_',$n), 300), + repeat(concat(' tc5_',$n), 300), + repeat(concat(' tc6_',$n), 300), + repeat(concat(' tc7_',$n), 300), + now(), (100.55+$n)); + + eval insert ignore into t2 values( + $n, $n, + repeat(concat(' tc3_',$n), 42), + repeat(concat(' tc4_',$n), 300), + repeat(concat(' tc5_',$n), 300), + repeat(concat(' tc6_',$n), 300), + repeat(concat(' tc7_',$n), 300), + now(), (100.55+$n)); + + eval insert ignore into t3 values( + $n, $n, + repeat(concat(' tc3_',$n), 42), + repeat(concat(' tc4_',$n), 300), + repeat(concat(' tc5_',$n), 300), + repeat(concat(' tc6_',$n), 300), + repeat(concat(' tc7_',$n), 300), + now(), (100.55+$n)); + + eval insert ignore into t4 values( + $n, $n, + repeat(concat(' tc3_',$n), 42), + repeat(concat(' tc4_',$n), 300), + repeat(concat(' tc5_',$n), 300), + repeat(concat(' tc6_',$n), 300), + repeat(concat(' tc7_',$n), 300), + now(), (100.55+$n)); + + eval insert ignore into t5 values( + $n, $n, + repeat(concat(' tc3_',$n), 42), + repeat(concat(' tc4_',$n), 300), + repeat(concat(' tc5_',$n), 300), + repeat(concat(' tc6_',$n), 300), + repeat(concat(' tc7_',$n), 300), + now(), (100.55+$n)); + + if ($n <= 3) + { + commit; + } + + if ($n > 3) + { + rollback; + } + + dec $n; + } + + # validate loading of the tables. + --enable_result_log + --enable_query_log + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + select count(*) from t5; + select count(*) from t6; + + # set the debug crash point and exercise them. + if ($cnt == 6) + { + set session debug="+d,ib_trunc_crash_during_drop_index_temp_table"; + --echo "---debug ib_trunc_crash_during_drop_index_temp_table point---" + } + if ($cnt == 5) + { + set session debug="+d,ib_trunc_crash_drop_reinit_done_create_to_start"; + --echo "---debug ib_trunc_crash_drop_reinit_done_create_to_start---" + } + + if ($cnt >= 5) { + --echo # Write file to make mysql-test-run.pl expect crash and restart + --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --echo # Run the crashing query + --error 2013 + truncate table t5; + --source include/wait_until_disconnected.inc + --enable_reconnect + --echo # Restart the MySQL server + --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --source include/wait_until_connected_again.inc + --disable_reconnect + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + --error ER_NO_SUCH_TABLE + select count(*) from t5; + select count(*) from t6; + } + + # set the debug crash point and exercise them. + if ($cnt == 6) + { + set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; + --echo "---debug ib_trunc_crash_on_drop_of_sec_index point---" + } + if ($cnt == 5) + { + set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; + --echo "---debug ib_trunc_crash_on_create_of_sec_index---" + } + if ($cnt == 4) + { + set session debug="+d,ib_trunc_crash_before_log_removal"; + --echo "---debug ib_trunc_crash_before_log_removal point---" + } + if ($cnt == 3) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 2) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 1) + { + set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; + --echo "---debug ib_trunc_crash_after_redo_log_write_complete point---" + } + + --echo # Write file to make mysql-test-run.pl expect crash and restart + --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --echo # Run the crashing query + --error 2013 + truncate table t1; + --source include/wait_until_disconnected.inc + --enable_reconnect + --echo # Restart the MySQL server + --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --source include/wait_until_connected_again.inc + --disable_reconnect + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + --error ER_NO_SUCH_TABLE + select count(*) from t5; + select count(*) from t6; + + if ($cnt == 6) + { + set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; + --echo "---debug ib_trunc_crash_on_drop_of_sec_index point---" + } + if ($cnt == 5) + { + set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; + --echo "---debug ib_trunc_crash_on_create_of_sec_index---" + } + if ($cnt == 4) + { + set session debug="+d,ib_trunc_crash_before_log_removal"; + --echo "---debug ib_trunc_crash_before_log_removal point---" + } + if ($cnt == 3) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 2) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 1) + { + set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; + --echo "---debug ib_trunc_crash_after_redo_log_write_complete point---" + } + + + --echo # Write file to make mysql-test-run.pl expect crash and restart + --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --echo # Run the crashing query + --error 2013 + truncate table t2; + --source include/wait_until_disconnected.inc + --enable_reconnect + --echo # Restart the MySQL server + --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --source include/wait_until_connected_again.inc + --disable_reconnect + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + --error ER_NO_SUCH_TABLE + select count(*) from t5; + select count(*) from t6; + + if ($cnt == 6) + { + set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; + --echo "---debug ib_trunc_crash_on_drop_of_sec_index point---" + } + if ($cnt == 5) + { + set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; + --echo "---debug ib_trunc_crash_on_create_of_sec_index---" + } + if ($cnt == 4) + { + set session debug="+d,ib_trunc_crash_before_log_removal"; + --echo "---debug ib_trunc_crash_before_log_removal point---" + } + if ($cnt == 3) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 2) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 1) + { + set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; + --echo "---debug ib_trunc_crash_after_redo_log_write_complete point---" + } + + + --echo # Write file to make mysql-test-run.pl expect crash and restart + --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --echo # Run the crashing query + --error 2013 + truncate table t3; + --source include/wait_until_disconnected.inc + --enable_reconnect + --echo # Restart the MySQL server + --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --source include/wait_until_connected_again.inc + --disable_reconnect + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + --error ER_NO_SUCH_TABLE + select count(*) from t5; + select count(*) from t6; + + + if ($cnt == 6) + { + set session debug="+d,ib_trunc_crash_on_drop_of_sec_index"; + --echo "---debug ib_trunc_crash_on_drop_of_sec_index point---" + } + if ($cnt == 5) + { + set session debug="+d,ib_trunc_crash_on_create_of_sec_index"; + --echo "---debug ib_trunc_crash_on_create_of_sec_index---" + } + if ($cnt == 4) + { + set session debug="+d,ib_trunc_crash_before_log_removal"; + --echo "---debug ib_trunc_crash_before_log_removal point---" + } + if ($cnt == 3) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 2) + { + set session debug="+d,ib_trunc_crash_after_truncate_done"; + --echo "---debug ib_trunc_crash_after_truncate_done point---" + } + if ($cnt == 1) + { + set session debug="+d,ib_trunc_crash_after_redo_log_write_complete"; + --echo "---debug ib_trunc_crash_after_redo_log_write_complete point---" + } + + --echo # Write file to make mysql-test-run.pl expect crash and restart + --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --echo # Run the crashing query + --error 2013 + truncate table t4; + --source include/wait_until_disconnected.inc + --enable_reconnect + --echo # Restart the MySQL server + --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --source include/wait_until_connected_again.inc + --disable_reconnect + select count(*) from t1; + select count(*) from t2; + select count(*) from t3; + select count(*) from t4; + --error ER_NO_SUCH_TABLE + select count(*) from t5; + select count(*) from t6; + + drop table t1, t2, t3, t4, t6; + + dec $cnt; + + --disable_query_log + eval set global innodb_file_per_table=$innodb_file_per_table_orig; + --enable_query_log +} + + + diff --git a/mysql-test/suite/innodb_zip/t/wl6501_crash_3.test b/mysql-test/suite/innodb_zip/t/wl6501_crash_3.test new file mode 100644 index 00000000000..3ec990b4715 --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/wl6501_crash_3.test @@ -0,0 +1,25 @@ +# +# WL#6501: make truncate table atomic +# + +# TC tries to hit crash point during truncate of +# compressed non-temp table residing in single tablespace +# with page-size=16k + +--source include/have_innodb.inc +--source include/have_innodb_16k.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +let $wl6501_file_per_table = 1; +let $wl6501_row_fmt = compressed; +let $wl6501_kbs = 16; +--source suite/innodb/include/innodb_wl6501_crash.inc + diff --git a/mysql-test/suite/innodb_zip/t/wl6501_crash_4.test b/mysql-test/suite/innodb_zip/t/wl6501_crash_4.test new file mode 100644 index 00000000000..f54df3c128c --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/wl6501_crash_4.test @@ -0,0 +1,27 @@ +# +# WL#6501: make truncate table atomic +# + +# TC tries to hit crash point during truncate of +# compressed non-temp table residing in single tablespace. +# with page-size=4k + +--source include/have_innodb.inc +--source include/have_innodb_4k.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +let $wl6501_file_per_table = 1; +let $wl6501_row_fmt = compressed; +let $wl6501_kbs = 4; +--source suite/innodb/include/innodb_wl6501_crash.inc + +let $wl6501_temp = temporary; +--source suite/innodb/include/innodb_wl6501_crash_temp.inc diff --git a/mysql-test/suite/innodb_zip/t/wl6501_crash_5.test b/mysql-test/suite/innodb_zip/t/wl6501_crash_5.test new file mode 100644 index 00000000000..2f9847ae5fb --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/wl6501_crash_5.test @@ -0,0 +1,25 @@ +# +# WL#6501: make truncate table atomic +# + +# TC tries to hit crash point during truncate of +# compressed non-temp table residing in single tablespace. +# with page-size=8k + +--source include/have_innodb.inc +--source include/have_innodb_8k.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +let $wl6501_file_per_table = 1; +let $wl6501_row_fmt = compressed; +let $wl6501_kbs = 8; +--source suite/innodb/include/innodb_wl6501_crash.inc + diff --git a/mysql-test/suite/innodb_zip/t/wl6501_scale_1.test b/mysql-test/suite/innodb_zip/t/wl6501_scale_1.test new file mode 100644 index 00000000000..e6392759d5e --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/wl6501_scale_1.test @@ -0,0 +1,37 @@ +# +# WL#6501: make truncate table atomic +# + +# load table with some significiant amount of data +# and then try truncate + +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc +--source include/have_innodb_16k.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + + +# Single-Tablespace/Non-Compressed +let $wl6501_file_per_table = 1; +let $wl6501_row_fmt = compact; +let $wl6501_kbs = 16; +--source suite/innodb_zip/include/innodb_wl6501_scale.inc + +# Single-Tablespace/Compressed +let $wl6501_file_per_table = 1; +let $wl6501_row_fmt = compressed; +let $wl6501_kbs = 16; +--source suite/innodb_zip/include/innodb_wl6501_scale.inc + +# System-Tablespace/Non-Compressed +let $wl6501_file_per_table = 0; +let $wl6501_row_fmt = compact; +let $wl6501_kbs = 16; +--source suite/innodb_zip/include/innodb_wl6501_scale.inc diff --git a/mysql-test/suite/mariabackup/truncate_during_backup.opt b/mysql-test/suite/mariabackup/truncate_during_backup.opt new file mode 100644 index 00000000000..e76044be888 --- /dev/null +++ b/mysql-test/suite/mariabackup/truncate_during_backup.opt @@ -0,0 +1 @@ +--loose-skip-innodb-unsafe-truncate diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index a82fa3ff5bc..0673de0054a 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2974,6 +2974,20 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME INNODB_UNSAFE_TRUNCATE +SESSION_VALUE NULL +GLOBAL_VALUE ON +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE ON +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Use backup-unsafe TRUNCATE TABLE for compatibility with xtrabackup (on by default) +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY YES +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_USE_ATOMIC_WRITES SESSION_VALUE NULL GLOBAL_VALUE ON diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index 594528ccbb1..2f9419efc62 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -1140,6 +1140,73 @@ dict_recreate_index_tree( return(FIL_NULL); } +/*******************************************************************//** +Truncates the index tree but don't update SYSTEM TABLES. +@return DB_SUCCESS or error */ +dberr_t +dict_truncate_index_tree_in_mem( +/*============================*/ + dict_index_t* index) /*!< in/out: index */ +{ + mtr_t mtr; + bool truncate; + ulint space = index->space; + + ut_ad(mutex_own(&dict_sys->mutex)); + ut_ad(dict_table_is_temporary(index->table)); + + ulint type = index->type; + ulint root_page_no = index->page; + + if (root_page_no == FIL_NULL) { + + /* The tree has been freed. */ + ib::warn() << "Trying to TRUNCATE a missing index of table " + << index->table->name << "!"; + + truncate = false; + } else { + truncate = true; + } + + bool found; + const page_size_t page_size(fil_space_get_page_size(space, + &found)); + + if (!found) { + + /* It is a single table tablespace and the .ibd file is + missing: do nothing */ + + ib::warn() + << "Trying to TRUNCATE a missing .ibd file of table " + << index->table->name << "!"; + } + + /* If table to truncate resides in its on own tablespace that will + be re-created on truncate then we can ignore freeing of existing + tablespace objects. */ + + if (truncate) { + btr_free(page_id_t(space, root_page_no), page_size); + } + + mtr_start(&mtr); + mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); + + root_page_no = btr_create( + type, space, page_size, index->id, index, NULL, &mtr); + + DBUG_EXECUTE_IF("ib_err_trunc_temp_recreate_index", + root_page_no = FIL_NULL;); + + index->page = root_page_no; + + mtr_commit(&mtr); + + return(index->page == FIL_NULL ? DB_ERROR : DB_SUCCESS); +} + /*********************************************************************//** Creates a table create graph. @return own: table create node */ diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 28874154c16..368144fe2b2 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -3112,6 +3112,154 @@ void fil_truncate_log(fil_space_t* space, ulint size, mtr_t* mtr) NULL, space->flags & ~FSP_FLAGS_MEM_MASK, mtr); } +/** Truncate the tablespace to needed size. +@param[in] space_id id of tablespace to truncate +@param[in] size_in_pages truncate size. +@return true if truncate was successful. */ +bool +fil_truncate_tablespace( + ulint space_id, + ulint size_in_pages) +{ + /* Step-1: Prepare tablespace for truncate. This involves + stopping all the new operations + IO on that tablespace + and ensuring that related pages are flushed to disk. */ + if (fil_prepare_for_truncate(space_id) != DB_SUCCESS) { + return(false); + } + + /* Step-2: Invalidate buffer pool pages belonging to the tablespace + to re-create. Remove all insert buffer entries for the tablespace */ + buf_LRU_flush_or_remove_pages(space_id, NULL); + + /* Step-3: Truncate the tablespace and accordingly update + the fil_space_t handler that is used to access this tablespace. */ + mutex_enter(&fil_system->mutex); + fil_space_t* space = fil_space_get_by_id(space_id); + + /* The following code must change when InnoDB supports + multiple datafiles per tablespace. */ + ut_a(UT_LIST_GET_LEN(space->chain) == 1); + + fil_node_t* node = UT_LIST_GET_FIRST(space->chain); + + ut_ad(node->is_open()); + + space->size = node->size = size_in_pages; + + bool success = os_file_truncate(node->name, node->handle, 0); + if (success) { + + os_offset_t size = os_offset_t(size_in_pages) * UNIV_PAGE_SIZE; + + success = os_file_set_size( + node->name, node->handle, size, + FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags)); + + if (success) { + space->stop_new_ops = false; + space->is_being_truncated = false; + } + } + + mutex_exit(&fil_system->mutex); + + return(success); +} + +/*******************************************************************//** +Prepare for truncating a single-table tablespace. +1) Check pending operations on a tablespace; +2) Remove all insert buffer entries for the tablespace; +@return DB_SUCCESS or error */ +dberr_t +fil_prepare_for_truncate( +/*=====================*/ + ulint id) /*!< in: space id */ +{ + char* path = 0; + fil_space_t* space = 0; + + ut_a(!is_system_tablespace(id)); + + dberr_t err = fil_check_pending_operations( + id, FIL_OPERATION_TRUNCATE, &space, &path); + + ut_free(path); + + if (err == DB_TABLESPACE_NOT_FOUND) { + ib::error() << "Cannot truncate tablespace " << id + << " because it is not found in the tablespace" + " memory cache."; + } + + return(err); +} + +/** Reinitialize the original tablespace header with the same space id +for single tablespace +@param[in] table table belongs to tablespace +@param[in] size size in blocks +@param[in] trx Transaction covering truncate */ +void +fil_reinit_space_header_for_table( + dict_table_t* table, + ulint size, + trx_t* trx) +{ + ulint id = table->space; + + ut_a(!is_system_tablespace(id)); + + /* Invalidate in the buffer pool all pages belonging + to the tablespace. The buffer pool scan may take long + time to complete, therefore we release dict_sys->mutex + and the dict operation lock during the scan and aquire + it again after the buffer pool scan.*/ + + /* Release the lock on the indexes too. So that + they won't violate the latch ordering. */ + dict_table_x_unlock_indexes(table); + row_mysql_unlock_data_dictionary(trx); + + /* Lock the search latch in shared mode to prevent user + from disabling AHI during the scan */ + btr_search_s_lock_all(); + DEBUG_SYNC_C("buffer_pool_scan"); + buf_LRU_flush_or_remove_pages(id, NULL); + btr_search_s_unlock_all(); + + row_mysql_lock_data_dictionary(trx); + + dict_table_x_lock_indexes(table); + + /* Remove all insert buffer entries for the tablespace */ + ibuf_delete_for_discarded_space(id); + + mutex_enter(&fil_system->mutex); + + fil_space_t* space = fil_space_get_by_id(id); + + /* The following code must change when InnoDB supports + multiple datafiles per tablespace. */ + ut_a(UT_LIST_GET_LEN(space->chain) == 1); + + fil_node_t* node = UT_LIST_GET_FIRST(space->chain); + + space->size = node->size = size; + + mutex_exit(&fil_system->mutex); + + mtr_t mtr; + + mtr_start(&mtr); + mtr.set_named_space(id); + + fsp_header_init(id, size, &mtr); + + mtr_commit(&mtr); +} + #ifdef UNIV_DEBUG /** Increase redo skipped count for a tablespace. @param[in] id space id */ @@ -4971,6 +5119,7 @@ fil_io( if (space->id != TRX_SYS_SPACE && UT_LIST_GET_LEN(space->chain) == 1 && (srv_is_tablespace_truncated(space->id) + || space->is_being_truncated || srv_was_tablespace_truncated(space)) && req_type.is_read()) { @@ -5877,6 +6026,7 @@ truncate_t::truncate( } space->stop_new_ops = false; + space->is_being_truncated = false; /* If we opened the file in this function, close it. */ if (!already_open) { diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 6ddcff7a55a..d4d5abeb32f 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -639,6 +639,7 @@ fsp_space_modify_check( ut_ad(space->purpose == FIL_TYPE_TEMPORARY || space->purpose == FIL_TYPE_IMPORT || space->redo_skipped_count + || space->is_being_truncated || srv_is_tablespace_truncated(space->id)); return; case MTR_LOG_ALL: diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 49f51c78f73..26e169b1ec3 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13452,6 +13452,37 @@ int ha_innobase::truncate() update_thd(); + if (srv_57_truncate) { + if (!trx_is_started(m_prebuilt->trx)) { + ++m_prebuilt->trx->will_lock; + } + + dberr_t err = row_truncate_table_for_mysql( + m_prebuilt->table, m_prebuilt->trx); + + int error; + + switch (err) { + case DB_TABLESPACE_DELETED: + case DB_TABLESPACE_NOT_FOUND: + ib_senderrf( + m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, + err == DB_TABLESPACE_DELETED + ? ER_TABLESPACE_DISCARDED + : ER_TABLESPACE_MISSING, + table->s->table_name.str); + error = HA_ERR_TABLESPACE_MISSING; + break; + default: + error = convert_error_code_to_mysql( + err, m_prebuilt->table->flags, + m_prebuilt->trx->mysql_thd); + break; + } + table->status = STATUS_NOT_FOUND; + DBUG_RETURN(error); + } + HA_CREATE_INFO info; mem_heap_t* heap = mem_heap_create(1000); dict_table_t* ib_table = m_prebuilt->table; @@ -20663,6 +20694,11 @@ static MYSQL_SYSVAR_BOOL(read_only, srv_read_only_mode, "Start InnoDB in read only mode (off by default)", NULL, NULL, FALSE); +static MYSQL_SYSVAR_BOOL(unsafe_truncate, srv_57_truncate, + PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, + "Use backup-unsafe TRUNCATE TABLE for compatibility with xtrabackup (on by default)", + NULL, NULL, TRUE); + static MYSQL_SYSVAR_BOOL(cmp_per_index_enabled, srv_cmp_per_index_enabled, PLUGIN_VAR_OPCMDARG, "Enable INFORMATION_SCHEMA.innodb_cmp_per_index," @@ -21042,6 +21078,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(random_read_ahead), MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(read_only), + MYSQL_SYSVAR(unsafe_truncate), MYSQL_SYSVAR(io_capacity), MYSQL_SYSVAR(io_capacity_max), MYSQL_SYSVAR(page_cleaners), diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h index e37ad66bc8c..5d149f24921 100644 --- a/storage/innobase/include/dict0crea.h +++ b/storage/innobase/include/dict0crea.h @@ -142,6 +142,14 @@ dict_create_index_tree_in_mem( dict_index_t* index, /*!< in/out: index */ const trx_t* trx); /*!< in: InnoDB transaction handle */ +/*******************************************************************//** +Truncates the index tree but don't update SYSTEM TABLES. +@return DB_SUCCESS or error */ +dberr_t +dict_truncate_index_tree_in_mem( +/*============================*/ + dict_index_t* index); /*!< in/out: index */ + /*******************************************************************//** Drops the index tree but don't update SYS_INDEXES table. */ void diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index c6b6ad92388..e738931485e 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -955,6 +955,37 @@ fil_space_t* fil_truncate_prepare(ulint space_id); void fil_truncate_log(fil_space_t* space, ulint size, mtr_t* mtr) MY_ATTRIBUTE((nonnull)); +/** Truncate the tablespace to needed size. +@param[in] space_id id of tablespace to truncate +@param[in] size_in_pages truncate size. +@return true if truncate was successful. */ +bool +fil_truncate_tablespace( + ulint space_id, + ulint size_in_pages); + +/*******************************************************************//** +Prepare for truncating a single-table tablespace. The tablespace +must be cached in the memory cache. +1) Check pending operations on a tablespace; +2) Remove all insert buffer entries for the tablespace; +@return DB_SUCCESS or error */ +dberr_t +fil_prepare_for_truncate( +/*=====================*/ + ulint id); /*!< in: space id */ + +/** Reinitialize the original tablespace header with the same space id +for single tablespace +@param[in] table table belongs to the tablespace +@param[in] size size in blocks +@param[in] trx Transaction covering truncate */ +void +fil_reinit_space_header_for_table( + dict_table_t* table, + ulint size, + trx_t* trx); + /*******************************************************************//** Closes a single-table tablespace. The tablespace must be cached in the memory cache. Free all pages used by the tablespace. diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 4759e5a85f4..4ff0056444b 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -519,7 +519,7 @@ roll back a retroactively introduced TRX_UNDO_RENAME_TABLE undo log record, MariaDB 10.2.18 and later will use the 10.3 format, but LOG_HEADER_SUBFORMAT 1 instead of 0. MariaDB 10.3 will use subformat 0 (5.7-style TRUNCATE) or 2 (MDEV-13564 backup-friendly TRUNCATE). */ -#define LOG_HEADER_FORMAT_CURRENT 103 +#define LOG_HEADER_FORMAT_10_3 103 /** The old MariaDB 10.2.2..10.2.17 log format */ #define LOG_HEADER_FORMAT_10_2 1 /** Future MariaDB 10.4 log format */ @@ -559,7 +559,7 @@ of log_sys->write_mutex, which should affect nothing for now. */ struct log_group_t{ /** number of files in the group */ ulint n_files; - /** format of the redo log: e.g., LOG_HEADER_FORMAT_CURRENT */ + /** format of the redo log: e.g., LOG_HEADER_FORMAT_10_3 */ uint32_t format; /** redo log subformat: 0 with separately logged TRUNCATE, 1 with fully redo-logged TRUNCATE */ diff --git a/storage/innobase/include/row0trunc.h b/storage/innobase/include/row0trunc.h index f9a20665a3b..4d6bdee225c 100644 --- a/storage/innobase/include/row0trunc.h +++ b/storage/innobase/include/row0trunc.h @@ -421,4 +421,9 @@ private: const char* log_file_name); }; +/** MySQL 5.7 TRUNCATE TABLE. +@param table table being truncated +@param trx transaction covering the truncate +@return error code or DB_SUCCESS */ +dberr_t row_truncate_table_for_mysql(dict_table_t* table, trx_t* trx); #endif /* row0trunc_h */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index ecd2914515d..f40cbf7f730 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -256,6 +256,9 @@ extern my_bool high_level_read_only; /** store to its own file each table created by an user; data dictionary tables are in the system tablespace 0 */ extern my_bool srv_file_per_table; +/** whether to use the MySQL 5.7 WL#6501 TRUNCATE TABLE implementation +that does not work with backup */ +extern my_bool srv_57_truncate; /** Sleep delay for threads waiting to enter InnoDB. In micro-seconds. */ extern ulong srv_thread_sleep_delay; /** Maximum sleep delay (in micro-seconds), value of 0 disables it.*/ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 95c637bccfd..b7d39440c75 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -790,10 +790,16 @@ log_init(ulint n_files) log_group_t* group = &log_sys->log; group->n_files = n_files; - group->format = srv_encrypt_log - ? LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED - : LOG_HEADER_FORMAT_CURRENT; - group->subformat = 1; + group->subformat = !srv_57_truncate; + if (srv_57_truncate) { + group->format = srv_encrypt_log + ? LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED + : LOG_HEADER_FORMAT_10_2; + } else { + group->format = srv_encrypt_log + ? LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED + : LOG_HEADER_FORMAT_10_3; + } group->file_size = srv_log_file_size; group->state = LOG_GROUP_OK; group->lsn = LOG_START_LSN; @@ -875,13 +881,15 @@ log_group_file_header_flush( ut_ad(!recv_no_log_write); ut_a(nth_file < group->n_files); ut_ad((group->format & ~LOG_HEADER_FORMAT_ENCRYPTED) - == LOG_HEADER_FORMAT_CURRENT); + == (srv_57_truncate + ? LOG_HEADER_FORMAT_10_2 + : LOG_HEADER_FORMAT_10_3)); buf = *(group->file_header_bufs + nth_file); memset(buf, 0, OS_FILE_LOG_BLOCK_SIZE); mach_write_to_4(buf + LOG_HEADER_FORMAT, group->format); - mach_write_to_4(buf + LOG_HEADER_SUBFORMAT, group->subformat); + mach_write_to_4(buf + LOG_HEADER_SUBFORMAT, !srv_57_truncate); mach_write_to_8(buf + LOG_HEADER_START_LSN, start_lsn); strcpy(reinterpret_cast(buf) + LOG_HEADER_CREATOR, LOG_HEADER_CREATOR_CURRENT); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 402e896ba15..2d2d9f2d674 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1165,10 +1165,10 @@ recv_find_max_checkpoint(ulint* max_field) switch (group->format) { case 0: return(recv_find_max_checkpoint_0(&group, max_field)); - case LOG_HEADER_FORMAT_CURRENT: - case LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED: case LOG_HEADER_FORMAT_10_2: case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED: + case LOG_HEADER_FORMAT_10_3: + case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: case LOG_HEADER_FORMAT_10_4: /* We can only parse the unencrypted LOG_HEADER_FORMAT_10_4. The encrypted format uses a larger redo log block trailer. */ @@ -1246,8 +1246,8 @@ recv_find_max_checkpoint(ulint* max_field) } switch (group->format) { - case LOG_HEADER_FORMAT_CURRENT: - case LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED: + case LOG_HEADER_FORMAT_10_3: + case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: if (group->subformat == 1) { /* 10.2 with new crash-safe TRUNCATE */ break; @@ -3431,8 +3431,8 @@ skip_apply: case LOG_HEADER_FORMAT_10_2: case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED: break; - case LOG_HEADER_FORMAT_CURRENT: - case LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED: + case LOG_HEADER_FORMAT_10_3: + case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: if (log_sys->log.subformat == 1) { /* 10.2 with new crash-safe TRUNCATE */ break; @@ -3769,6 +3769,7 @@ recv_recovery_rollback_active(void) /* Drop partially created indexes. */ row_merge_drop_temp_indexes(); /* Drop garbage tables. */ + if (!srv_57_truncate) row_mysql_drop_garbage_tables(); /* Drop any auxiliary tables that were not dropped when the diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 4423ec90dff..4e08377916d 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1629,7 +1629,8 @@ row_ins_check_foreign_constraint( if (check_table == NULL || !check_table->is_readable() - || check_index == NULL) { + || check_index == NULL + || fil_space_get(check_table->space)->is_being_truncated) { if (!srv_read_only_mode && check_ref) { FILE* ef = dict_foreign_err_file; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 1491921bece..5f558203ca4 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -4403,7 +4403,7 @@ row_rename_table_for_mysql( goto funct_exit; } - if (!table->is_temporary()) { + if (!table->is_temporary() && !srv_57_truncate) { err = trx_undo_report_rename(trx, table); if (err != DB_SUCCESS) { diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc index 79bffe498dd..c6c752a92b8 100644 --- a/storage/innobase/row/row0trunc.cc +++ b/storage/innobase/row/row0trunc.cc @@ -50,6 +50,8 @@ bool truncate_t::s_fix_up_active = false; truncate_t::tables_t truncate_t::s_tables; truncate_t::truncated_tables_t truncate_t::s_truncated_tables; +static const byte magic[] = { 0x01, 0xf3, 0xa1, 0x20 }; + /** Iterator over the the raw records in an index, doesn't support MVCC. */ class IndexIterator { @@ -240,6 +242,301 @@ protected: const bool m_noredo; }; +/** +Creates a TRUNCATE log record with space id, table name, data directory path, +tablespace flags, table format, index ids, index types, number of index fields +and index field information of the table. */ +class TruncateLogger : public Callback { + +public: + /** + Constructor + + @param table Table to truncate + @param flags tablespace falgs */ + TruncateLogger( + dict_table_t* table, + ulint flags, + table_id_t new_table_id) + : + Callback(table->id, false), + m_table(table), + m_flags(flags), + m_truncate(table->id, new_table_id, table->data_dir_path), + m_log_file_name() + { + /* Do nothing */ + } + + /** + Initialize Truncate Logger by constructing Truncate Log File Name. + + @return DB_SUCCESS or error code. */ + dberr_t init() + { + /* Construct log file name. */ + ulint log_file_name_buf_sz = + strlen(srv_log_group_home_dir) + + (22 + 22 + sizeof "ib_trunc.log"); + + m_log_file_name = UT_NEW_ARRAY_NOKEY(char, log_file_name_buf_sz); + if (m_log_file_name == NULL) { + return(DB_OUT_OF_MEMORY); + } + memset(m_log_file_name, 0, log_file_name_buf_sz); + + strcpy(m_log_file_name, srv_log_group_home_dir); + ulint log_file_name_len = strlen(m_log_file_name); + if (m_log_file_name[log_file_name_len - 1] + != OS_PATH_SEPARATOR) { + + m_log_file_name[log_file_name_len] + = OS_PATH_SEPARATOR; + log_file_name_len = strlen(m_log_file_name); + } + + snprintf(m_log_file_name + log_file_name_len, + log_file_name_buf_sz - log_file_name_len, + "ib_%u_" IB_ID_FMT "_trunc.log", + m_table->space, m_table->id); + + return(DB_SUCCESS); + + } + + /** + Destructor */ + ~TruncateLogger() + { + if (m_log_file_name != NULL) { + bool exist; + os_file_delete_if_exists( + innodb_log_file_key, m_log_file_name, &exist); + UT_DELETE_ARRAY(m_log_file_name); + m_log_file_name = NULL; + } + } + + /** + @param mtr mini-transaction covering the read + @param pcur persistent cursor used for reading + @return DB_SUCCESS or error code */ + dberr_t operator()(mtr_t* mtr, btr_pcur_t* pcur); + + /** Called after iteratoring over the records. + @return true if invariant satisfied. */ + bool debug() const + { + /* We must find all the index entries on disk. */ + return(UT_LIST_GET_LEN(m_table->indexes) + == m_truncate.indexes()); + } + + /** + Write the TRUNCATE log + @return DB_SUCCESS or error code */ + dberr_t log() const + { + dberr_t err = DB_SUCCESS; + + if (m_log_file_name == 0) { + return(DB_ERROR); + } + + bool ret; + os_file_t handle = os_file_create( + innodb_log_file_key, m_log_file_name, + OS_FILE_CREATE, OS_FILE_NORMAL, + OS_LOG_FILE, srv_read_only_mode, &ret); + if (!ret) { + return(DB_IO_ERROR); + } + + + ulint sz = UNIV_PAGE_SIZE; + void* buf = ut_zalloc_nokey(sz + UNIV_PAGE_SIZE); + if (buf == 0) { + os_file_close(handle); + return(DB_OUT_OF_MEMORY); + } + + /* Align the memory for file i/o if we might have O_DIRECT set*/ + byte* log_buf = static_cast( + ut_align(buf, UNIV_PAGE_SIZE)); + + lsn_t lsn = log_get_lsn(); + + /* Generally loop should exit in single go but + just for those 1% of rare cases we need to assume + corner case. */ + do { + /* First 4 bytes are reserved for magic number + which is currently 0. */ + err = m_truncate.write( + log_buf + 4, log_buf + sz - 4, + m_table->space, m_table->name.m_name, + m_flags, m_table->flags, lsn); + + DBUG_EXECUTE_IF("ib_err_trunc_oom_logging", + err = DB_FAIL;); + + if (err != DB_SUCCESS) { + ut_ad(err == DB_FAIL); + ut_free(buf); + sz *= 2; + buf = ut_zalloc_nokey(sz + UNIV_PAGE_SIZE); + DBUG_EXECUTE_IF("ib_err_trunc_oom_logging", + ut_free(buf); + buf = 0;); + if (buf == 0) { + os_file_close(handle); + return(DB_OUT_OF_MEMORY); + } + log_buf = static_cast( + ut_align(buf, UNIV_PAGE_SIZE)); + } + + } while (err != DB_SUCCESS); + + dberr_t io_err; + + IORequest request(IORequest::WRITE); + + io_err = os_file_write( + request, m_log_file_name, handle, log_buf, 0, sz); + + if (io_err != DB_SUCCESS) { + + ib::error() + << "IO: Failed to write the file size to '" + << m_log_file_name << "'"; + + /* Preserve the original error code */ + if (err == DB_SUCCESS) { + err = io_err; + } + } + + os_file_flush(handle); + os_file_close(handle); + + ut_free(buf); + + /* Why we need MLOG_TRUNCATE when we have truncate_log for + recovery? + - truncate log can protect us if crash happens while truncate + is active. Once truncate is done truncate log is removed. + - If crash happens post truncate and system is yet to + checkpoint, on recovery we would see REDO records from action + before truncate (unless we explicitly checkpoint before + returning from truncate API. Costly alternative so rejected). + - These REDO records may reference a page that doesn't exist + post truncate so we need a mechanism to skip all such REDO + records. MLOG_TRUNCATE records space_id and lsn that exactly + serve the purpose. + - If checkpoint happens post truncate and crash happens post + this point then neither MLOG_TRUNCATE nor REDO record + from action before truncate are accessible. */ + if (!is_system_tablespace(m_table->space)) { + mtr_t mtr; + byte* log_ptr; + + mtr_start(&mtr); + + log_ptr = mlog_open(&mtr, 11 + 8); + log_ptr = mlog_write_initial_log_record_low( + MLOG_TRUNCATE, m_table->space, 0, + log_ptr, &mtr); + + mach_write_to_8(log_ptr, lsn); + log_ptr += 8; + + mlog_close(&mtr, log_ptr); + mtr_commit(&mtr); + } + + return(err); + } + + /** + Indicate completion of truncate log by writing magic-number. + File will be removed from the system but to protect against + unlink (File-System) anomalies we ensure we write magic-number. */ + void done() + { + if (m_log_file_name == 0) { + return; + } + + bool ret; + os_file_t handle = os_file_create_simple_no_error_handling( + innodb_log_file_key, m_log_file_name, + OS_FILE_OPEN, OS_FILE_READ_WRITE, + srv_read_only_mode, &ret); + DBUG_EXECUTE_IF("ib_err_trunc_writing_magic_number", + os_file_close(handle); + ret = false;); + if (!ret) { + ib::error() << "Failed to open truncate log file " + << m_log_file_name << "." + " If server crashes before truncate log is" + " removed make sure it is manually removed" + " before restarting server"; + os_file_delete(innodb_log_file_key, m_log_file_name); + return; + } + + if (os_file_write(IORequest(IORequest::WRITE), + m_log_file_name, handle, magic, 0, + sizeof magic) != DB_SUCCESS) { + ib::error() + << "IO: Failed to write the magic number to '" + << m_log_file_name << "'"; + } + + DBUG_EXECUTE_IF("ib_trunc_crash_after_updating_magic_no", + DBUG_SUICIDE();); + os_file_flush(handle); + os_file_close(handle); + DBUG_EXECUTE_IF("ib_trunc_crash_after_logging_complete", + log_buffer_flush_to_disk(); + os_thread_sleep(1000000); + DBUG_SUICIDE();); + os_file_delete(innodb_log_file_key, m_log_file_name); + } + +private: + /** Lookup the index using the index id. + @return index instance if found else NULL */ + const dict_index_t* find(index_id_t id) const + { + for (const dict_index_t* index = UT_LIST_GET_FIRST( + m_table->indexes); + index != NULL; + index = UT_LIST_GET_NEXT(indexes, index)) { + + if (index->id == id) { + return(index); + } + } + + return(NULL); + } + +private: + /** Table to be truncated */ + dict_table_t* m_table; + + /** Tablespace flags */ + ulint m_flags; + + /** Collect table to truncate information */ + truncate_t m_truncate; + + /** Truncate log file name. */ + char* m_log_file_name; +}; + /** Scan to find out truncate log file from the given directory path. @@ -355,7 +652,7 @@ TruncateLogParser::parse( break; } - if (mach_read_from_4(log_buf) == 32743712) { + if (!memcmp(log_buf, magic, sizeof magic)) { /* Truncate action completed. Avoid parsing the file. */ os_file_close(handle); @@ -551,6 +848,58 @@ private: bool m_table_found; }; +/** +@param mtr mini-transaction covering the read +@param pcur persistent cursor used for reading +@return DB_SUCCESS or error code */ +dberr_t +TruncateLogger::operator()(mtr_t* mtr, btr_pcur_t* pcur) +{ + ulint len; + const byte* field; + rec_t* rec = btr_pcur_get_rec(pcur); + truncate_t::index_t index; + + field = rec_get_nth_field_old( + rec, DICT_FLD__SYS_INDEXES__TYPE, &len); + ut_ad(len == 4); + index.m_type = mach_read_from_4(field); + + field = rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__ID, &len); + ut_ad(len == 8); + index.m_id = mach_read_from_8(field); + + field = rec_get_nth_field_old( + rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len); + ut_ad(len == 4); + index.m_root_page_no = mach_read_from_4(field); + + /* For compressed tables we need to store extra meta-data + required during btr_create(). */ + if (FSP_FLAGS_GET_ZIP_SSIZE(m_flags)) { + + const dict_index_t* dict_index = find(index.m_id); + + if (dict_index != NULL) { + + dberr_t err = index.set(dict_index); + + if (err != DB_SUCCESS) { + m_truncate.clear(); + return(err); + } + + } else { + ib::warn() << "Index id " << index.m_id + << " not found"; + } + } + + m_truncate.add(index); + + return(DB_SUCCESS); +} + /** Drop an index in the table. @@ -736,6 +1085,251 @@ TableLocator::operator()(mtr_t* mtr, btr_pcur_t* pcur) return(DB_SUCCESS); } +/** +Rollback the transaction and release the index locks. +Drop indexes if table is corrupted so that drop/create +sequence works as expected. + +@param table table to truncate +@param trx transaction covering the TRUNCATE +@param new_id new table id that was suppose to get assigned + to the table if truncate executed successfully. +@param has_internal_doc_id indicate existence of fts index +@param no_redo if true, turn-off redo logging +@param corrupted table corrupted status +@param unlock_index if true then unlock indexes before action */ +static +void +row_truncate_rollback( + dict_table_t* table, + trx_t* trx, + table_id_t new_id, + bool has_internal_doc_id, + bool no_redo, + bool corrupted, + bool unlock_index) +{ + if (unlock_index) { + dict_table_x_unlock_indexes(table); + } + + trx->error_state = DB_SUCCESS; + + trx_rollback_to_savepoint(trx, NULL); + + trx->error_state = DB_SUCCESS; + + if (corrupted && !dict_table_is_temporary(table)) { + + /* Cleanup action to ensure we don't left over stale entries + if we are marking table as corrupted. This will ensure + it can be recovered using drop/create sequence. */ + dict_table_x_lock_indexes(table); + + DropIndex dropIndex(table, no_redo); + + SysIndexIterator().for_each(dropIndex); + + dict_table_x_unlock_indexes(table); + + for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); + index != NULL; + index = UT_LIST_GET_NEXT(indexes, index)) { + + dict_set_corrupted(index, trx, "TRUNCATE TABLE"); + } + + if (has_internal_doc_id) { + + ut_ad(!trx_is_started(trx)); + + table_id_t id = table->id; + + table->id = new_id; + + fts_drop_tables(trx, table); + + table->id = id; + + ut_ad(trx_is_started(trx)); + + trx_commit_for_mysql(trx); + } + + } else if (corrupted && dict_table_is_temporary(table)) { + + dict_table_x_lock_indexes(table); + + for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); + index != NULL; + index = UT_LIST_GET_NEXT(indexes, index)) { + + dict_drop_index_tree_in_mem(index, index->page); + + index->page = FIL_NULL; + } + + dict_table_x_unlock_indexes(table); + } + + table->corrupted = corrupted; +} + +/** +Finish the TRUNCATE operations for both commit and rollback. + +@param table table being truncated +@param trx transaction covering the truncate +@param fsp_flags tablespace flags +@param logger table to truncate information logger +@param err status of truncate operation + +@return DB_SUCCESS or error code */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_complete( + dict_table_t* table, + trx_t* trx, + ulint fsp_flags, + TruncateLogger* &logger, + dberr_t err) +{ + bool is_file_per_table = dict_table_is_file_per_table(table); + + /* Add the table back to FTS optimize background thread. */ + if (table->fts) { + fts_optimize_add_table(table); + } + + row_mysql_unlock_data_dictionary(trx); + + DEBUG_SYNC_C("ib_trunc_table_trunc_completing"); + + if (!dict_table_is_temporary(table)) { + + DBUG_EXECUTE_IF("ib_trunc_crash_before_log_removal", + log_buffer_flush_to_disk(); + os_thread_sleep(500000); + DBUG_SUICIDE();); + + /* Note: We don't log-checkpoint instead we have written + a special REDO log record MLOG_TRUNCATE that is used to + avoid applying REDO records before truncate for crash + that happens post successful truncate completion. */ + + if (logger != NULL) { + logger->done(); + UT_DELETE(logger); + logger = NULL; + } + } + + /* If non-temp file-per-table tablespace... */ + if (is_file_per_table + && !dict_table_is_temporary(table) + && fsp_flags != ULINT_UNDEFINED) { + + /* This function will reset back the stop_new_ops + and is_being_truncated so that fil-ops can re-start. */ + dberr_t err2 = truncate_t::truncate( + table->space, + table->data_dir_path, + table->name.m_name, fsp_flags, false); + + if (err2 != DB_SUCCESS) { + return(err2); + } + } + + if (err == DB_SUCCESS) { + dict_stats_update(table, DICT_STATS_EMPTY_TABLE); + } + + trx->op_info = ""; + + /* For temporary tables or if there was an error, we need to reset + the dict operation flags. */ + trx->ddl = false; + trx->dict_operation = TRX_DICT_OP_NONE; + + ut_ad(!trx_is_started(trx)); + + srv_wake_master_thread(); + + DBUG_EXECUTE_IF("ib_trunc_crash_after_truncate_done", + DBUG_SUICIDE();); + + return(err); +} + +/** +Handle FTS truncate issues. +@param table table being truncated +@param new_id new id for the table +@param trx transaction covering the truncate +@return DB_SUCCESS or error code. */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_fts( + dict_table_t* table, + table_id_t new_id, + trx_t* trx) +{ + dict_table_t fts_table; + + fts_table.id = new_id; + fts_table.name = table->name; + fts_table.flags2 = table->flags2; + fts_table.flags = table->flags; + fts_table.space = table->space; + + /* table->data_dir_path is used for FTS AUX table + creation. */ + if (DICT_TF_HAS_DATA_DIR(table->flags) + && table->data_dir_path == NULL) { + dict_get_and_save_data_dir_path(table, true); + ut_ad(table->data_dir_path != NULL); + } + + fts_table.data_dir_path = table->data_dir_path; + + dberr_t err; + + err = fts_create_common_tables( + trx, &fts_table, table->name.m_name, TRUE); + + for (ulint i = 0; + i < ib_vector_size(table->fts->indexes) && err == DB_SUCCESS; + i++) { + + dict_index_t* fts_index; + + fts_index = static_cast( + ib_vector_getp(table->fts->indexes, i)); + + err = fts_create_index_tables_low( + trx, fts_index, table->name.m_name, new_id); + } + + DBUG_EXECUTE_IF("ib_err_trunc_during_fts_trunc", + err = DB_ERROR;); + + if (err != DB_SUCCESS) { + + trx->error_state = DB_SUCCESS; + trx_rollback_to_savepoint(trx, NULL); + trx->error_state = DB_SUCCESS; + + ib::error() << "Unable to truncate FTS index for table " + << table->name; + } else { + + ut_ad(trx_is_started(trx)); + } + + return(err); +} + /** Update system table to reflect new table id. @param old_table_id old table id @@ -876,6 +1470,626 @@ row_truncate_update_sys_tables_during_fix_up( return(err); } +/** +Truncate also results in assignment of new table id, update the system +SYSTEM TABLES with the new id. +@param table, table being truncated +@param new_id, new table id +@param has_internal_doc_id, has doc col (fts) +@param no_redo if true, turn-off redo logging +@param trx transaction handle +@return error code or DB_SUCCESS */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_update_system_tables( + dict_table_t* table, + table_id_t new_id, + bool has_internal_doc_id, + bool no_redo, + trx_t* trx) +{ + dberr_t err = DB_SUCCESS; + + ut_a(!dict_table_is_temporary(table)); + + err = row_truncate_update_table_id(table->id, new_id, FALSE, trx); + + DBUG_EXECUTE_IF("ib_err_trunc_during_sys_table_update", + err = DB_ERROR;); + + if (err != DB_SUCCESS) { + + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, true, false); + + ib::error() << "Unable to assign a new identifier to table " + << table->name << " after truncating it. Marked the" + " table as corrupted. In-memory representation is now" + " different from the on-disk representation."; + err = DB_ERROR; + } else { + /* Drop the old FTS index */ + if (has_internal_doc_id) { + + ut_ad(trx_is_started(trx)); + + fts_drop_tables(trx, table); + + DBUG_EXECUTE_IF("ib_truncate_crash_while_fts_cleanup", + DBUG_SUICIDE();); + + ut_ad(trx_is_started(trx)); + } + + DBUG_EXECUTE_IF("ib_trunc_crash_after_fts_drop", + log_buffer_flush_to_disk(); + os_thread_sleep(2000000); + DBUG_SUICIDE();); + + dict_table_change_id_in_cache(table, new_id); + + /* Reset the Doc ID in cache to 0 */ + if (has_internal_doc_id && table->fts->cache != NULL) { + DBUG_EXECUTE_IF("ib_trunc_sleep_before_fts_cache_clear", + os_thread_sleep(10000000);); + + table->fts->fts_status |= TABLE_DICT_LOCKED; + fts_update_next_doc_id(trx, table, NULL, 0); + fts_cache_clear(table->fts->cache); + fts_cache_init(table->fts->cache); + table->fts->fts_status &= uint(~TABLE_DICT_LOCKED); + } + } + + return(err); +} + +/** +Prepare for the truncate process. On success all of the table's indexes will +be locked in X mode. +@param table table to truncate +@param flags tablespace flags +@return error code or DB_SUCCESS */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_prepare(dict_table_t* table, ulint* flags) +{ + ut_ad(!dict_table_is_temporary(table)); + ut_ad(dict_table_is_file_per_table(table)); + + *flags = fil_space_get_flags(table->space); + + ut_ad(!dict_table_is_temporary(table)); + + dict_get_and_save_data_dir_path(table, true); + + if (*flags != ULINT_UNDEFINED) { + + dberr_t err = fil_prepare_for_truncate(table->space); + + if (err != DB_SUCCESS) { + return(err); + } + } + + return(DB_SUCCESS); +} + +/** +Do foreign key checks before starting TRUNCATE. +@param table table being truncated +@param trx transaction covering the truncate +@return DB_SUCCESS or error code */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_foreign_key_checks( + const dict_table_t* table, + const trx_t* trx) +{ + /* Check if the table is referenced by foreign key constraints from + some other table (not the table itself) */ + + dict_foreign_set::iterator it + = std::find_if(table->referenced_set.begin(), + table->referenced_set.end(), + dict_foreign_different_tables()); + + if (!srv_read_only_mode + && it != table->referenced_set.end() + && trx->check_foreigns) { + + dict_foreign_t* foreign = *it; + + FILE* ef = dict_foreign_err_file; + + /* We only allow truncating a referenced table if + FOREIGN_KEY_CHECKS is set to 0 */ + + mutex_enter(&dict_foreign_err_mutex); + + rewind(ef); + + ut_print_timestamp(ef); + + fputs(" Cannot truncate table ", ef); + ut_print_name(ef, trx, table->name.m_name); + fputs(" by DROP+CREATE\n" + "InnoDB: because it is referenced by ", ef); + ut_print_name(ef, trx, foreign->foreign_table_name); + putc('\n', ef); + + mutex_exit(&dict_foreign_err_mutex); + + return(DB_ERROR); + } + + /* TODO: could we replace the counter n_foreign_key_checks_running + with lock checks on the table? Acquire here an exclusive lock on the + table, and rewrite lock0lock.cc and the lock wait in srv0srv.cc so that + they can cope with the table having been truncated here? Foreign key + checks take an IS or IX lock on the table. */ + + if (table->n_foreign_key_checks_running > 0) { + ib::warn() << "Cannot truncate table " << table->name + << " because there is a foreign key check running on" + " it."; + + return(DB_ERROR); + } + + return(DB_SUCCESS); +} + +/** +Do some sanity checks before starting the actual TRUNCATE. +@param table table being truncated +@return DB_SUCCESS or error code */ +static MY_ATTRIBUTE((warn_unused_result)) +dberr_t +row_truncate_sanity_checks( + const dict_table_t* table) +{ + if (dict_table_is_discarded(table)) { + + return(DB_TABLESPACE_DELETED); + + } else if (!table->is_readable()) { + if (fil_space_get(table->space) == NULL) { + return(DB_TABLESPACE_NOT_FOUND); + + } else { + return(DB_DECRYPTION_FAILED); + } + } else if (dict_table_is_corrupted(table)) { + + return(DB_TABLE_CORRUPT); + } + + return(DB_SUCCESS); +} + +/** +Truncates a table for MySQL. +@param table table being truncated +@param trx transaction covering the truncate +@return error code or DB_SUCCESS */ +dberr_t row_truncate_table_for_mysql(dict_table_t* table, trx_t* trx) +{ + bool is_file_per_table = dict_table_is_file_per_table(table); + dberr_t err; +#ifdef UNIV_DEBUG + ulint old_space = table->space; +#endif /* UNIV_DEBUG */ + TruncateLogger* logger = NULL; + + /* Understanding the truncate flow. + + Step-1: Perform intiial sanity check to ensure table can be truncated. + This would include check for tablespace discard status, ibd file + missing, etc .... + + Step-2: Start transaction (only for non-temp table as temp-table don't + modify any data on disk doesn't need transaction object). + + Step-3: Validate ownership of needed locks (Exclusive lock). + Ownership will also ensure there is no active SQL queries, INSERT, + SELECT, ..... + + Step-4: Stop all the background process associated with table. + + Step-5: There are few foreign key related constraint under which + we can't truncate table (due to referential integrity unless it is + turned off). Ensure this condition is satisfied. + + Step-6: Truncate operation can be rolled back in case of error + till some point. Associate rollback segment to record undo log. + + Step-7: Generate new table-id. + Why we need new table-id ? + Purge and rollback case: we assign a new table id for the table. + Since purge and rollback look for the table based on the table id, + they see the table as 'dropped' and discard their operations. + + Step-8: Log information about tablespace which includes + table and index information. If there is a crash in the next step + then during recovery we will attempt to fixup the operation. + + Step-9: Drop all indexes (this include freeing of the pages + associated with them). + + Step-10: Re-create new indexes. + + Step-11: Update new table-id to in-memory cache (dictionary), + on-disk (INNODB_SYS_TABLES). INNODB_SYS_INDEXES also needs to + be updated to reflect updated root-page-no of new index created + and updated table-id. + + Step-12: Cleanup Stage. Reset auto-inc value to 1. + Release all the locks. + Commit the transaction. Update trx operation state. + + Notes: + - On error, log checkpoint is done followed writing of magic number to + truncate log file. If servers crashes after truncate, fix-up action + will not be applied. + + - log checkpoint is done before starting truncate table to ensure + that previous REDO log entries are not applied if current truncate + crashes. Consider following use-case: + - create table .... insert/load table .... truncate table (crash) + - on restart table is restored .... truncate table (crash) + - on restart (assuming default log checkpoint is not done) will have + 2 REDO log entries for same table. (Note 2 REDO log entries + for different table is not an issue). + For system-tablespace we can't truncate the tablespace so we need + to initiate a local cleanup that involves dropping of indexes and + re-creating them. If we apply stale entry we might end-up issuing + drop on wrong indexes. + + - Insert buffer: TRUNCATE TABLE is analogous to DROP TABLE, + so we do not have to remove insert buffer records, as the + insert buffer works at a low level. If a freed page is later + reallocated, the allocator will remove the ibuf entries for + it. When we prepare to truncate *.ibd files, we remove all entries + for the table in the insert buffer tree. This is not strictly + necessary, but we can free up some space in the system tablespace. + + - Linear readahead and random readahead: we use the same + method as in 3) to discard ongoing operations. (This is only + relevant for TRUNCATE TABLE by TRUNCATE TABLESPACE.) + Ensure that the table will be dropped by trx_rollback_active() in + case of a crash. + */ + + /*-----------------------------------------------------------------*/ + /* Step-1: Perform intiial sanity check to ensure table can be + truncated. This would include check for tablespace discard status, + ibd file missing, etc .... */ + err = row_truncate_sanity_checks(table); + if (err != DB_SUCCESS) { + return(err); + + } + + /* Step-2: Start transaction (only for non-temp table as temp-table + don't modify any data on disk doesn't need transaction object). */ + if (!dict_table_is_temporary(table)) { + if (table->fts) { + fts_optimize_remove_table(table); + } + + /* Avoid transaction overhead for temporary table DDL. */ + trx_start_for_ddl(trx, TRX_DICT_OP_TABLE); + } + + DEBUG_SYNC_C("row_trunc_before_dict_lock"); + + /* Step-3: Validate ownership of needed locks (Exclusive lock). + Ownership will also ensure there is no active SQL queries, INSERT, + SELECT, .....*/ + trx->op_info = "truncating table"; + ut_a(trx->dict_operation_lock_mode == 0); + row_mysql_lock_data_dictionary(trx); + ut_ad(mutex_own(&dict_sys->mutex)); + ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X)); + + /* Step-4: Stop all the background process associated with table. */ + dict_stats_wait_bg_to_stop_using_table(table, trx); + + /* Step-5: There are few foreign key related constraint under which + we can't truncate table (due to referential integrity unless it is + turned off). Ensure this condition is satisfied. */ + ulint fsp_flags = ULINT_UNDEFINED; + err = row_truncate_foreign_key_checks(table, trx); + if (err != DB_SUCCESS) { + trx_rollback_to_savepoint(trx, NULL); + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + + /* Remove all locks except the table-level X lock. */ + lock_remove_all_on_table(table, FALSE); + trx->table_id = table->id; + trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); + + /* Step-6: Truncate operation can be rolled back in case of error + till some point. Associate rollback segment to record undo log. */ + if (!dict_table_is_temporary(table)) { + mutex_enter(&trx->undo_mutex); + + trx_undo_t** pundo = &trx->rsegs.m_redo.update_undo; + err = trx_undo_assign_undo( + trx, trx->rsegs.m_redo.rseg, pundo, TRX_UNDO_UPDATE); + + mutex_exit(&trx->undo_mutex); + + DBUG_EXECUTE_IF("ib_err_trunc_assigning_undo_log", + err = DB_ERROR;); + if (err != DB_SUCCESS) { + trx_rollback_to_savepoint(trx, NULL); + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } + + /* Step-7: Generate new table-id. + Why we need new table-id ? + Purge and rollback: we assign a new table id for the + table. Since purge and rollback look for the table based on + the table id, they see the table as 'dropped' and discard + their operations. */ + table_id_t new_id; + dict_hdr_get_new_id(&new_id, NULL, NULL, table, false); + + /* Check if table involves FTS index. */ + bool has_internal_doc_id = + dict_table_has_fts_index(table) + || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID); + + bool no_redo = is_file_per_table && !has_internal_doc_id; + + /* Step-8: Log information about tablespace which includes + table and index information. If there is a crash in the next step + then during recovery we will attempt to fixup the operation. */ + + /* Lock all index trees for this table, as we will truncate + the table/index and possibly change their metadata. All + DML/DDL are blocked by table level X lock, with a few exceptions + such as queries into information schema about the table, + MySQL could try to access index stats for this kind of query, + we need to use index locks to sync up */ + dict_table_x_lock_indexes(table); + + if (!dict_table_is_temporary(table)) { + + if (is_file_per_table) { + + err = row_truncate_prepare(table, &fsp_flags); + + DBUG_EXECUTE_IF("ib_err_trunc_preparing_for_truncate", + err = DB_ERROR;); + + if (err != DB_SUCCESS) { + row_truncate_rollback( + table, trx, new_id, + has_internal_doc_id, + no_redo, false, true); + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } else { + fsp_flags = fil_space_get_flags(table->space); + + DBUG_EXECUTE_IF("ib_err_trunc_preparing_for_truncate", + fsp_flags = ULINT_UNDEFINED;); + + if (fsp_flags == ULINT_UNDEFINED) { + row_truncate_rollback( + table, trx, new_id, + has_internal_doc_id, + no_redo, false, true); + return(row_truncate_complete( + table, trx, fsp_flags, + logger, DB_ERROR)); + } + } + + logger = UT_NEW_NOKEY(TruncateLogger( + table, fsp_flags, new_id)); + + err = logger->init(); + if (err != DB_SUCCESS) { + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, false, true); + return(row_truncate_complete( + table, trx, fsp_flags, logger, DB_ERROR)); + + } + + err = SysIndexIterator().for_each(*logger); + if (err != DB_SUCCESS) { + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, false, true); + return(row_truncate_complete( + table, trx, fsp_flags, logger, DB_ERROR)); + + } + + ut_ad(logger->debug()); + + err = logger->log(); + + if (err != DB_SUCCESS) { + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, false, true); + return(row_truncate_complete( + table, trx, fsp_flags, logger, DB_ERROR)); + } + } + + DBUG_EXECUTE_IF("ib_trunc_crash_after_redo_log_write_complete", + log_buffer_flush_to_disk(); + os_thread_sleep(3000000); + DBUG_SUICIDE();); + + /* Step-9: Drop all indexes (free index pages associated with these + indexes) */ + if (!dict_table_is_temporary(table)) { + + DropIndex dropIndex(table, no_redo); + + err = SysIndexIterator().for_each(dropIndex); + + if (err != DB_SUCCESS) { + + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, true, true); + + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } else { + /* For temporary tables we don't have entries in SYSTEM TABLES*/ + ut_ad(fsp_is_system_temporary(table->space)); + for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); + index != NULL; + index = UT_LIST_GET_NEXT(indexes, index)) { + + err = dict_truncate_index_tree_in_mem(index); + + if (err != DB_SUCCESS) { + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, true, true); + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + + DBUG_EXECUTE_IF( + "ib_trunc_crash_during_drop_index_temp_table", + log_buffer_flush_to_disk(); + os_thread_sleep(2000000); + DBUG_SUICIDE();); + } + } + + if (is_file_per_table && fsp_flags != ULINT_UNDEFINED) { + /* A single-table tablespace has initially + FIL_IBD_FILE_INITIAL_SIZE number of pages allocated and an + extra page is allocated for each of the indexes present. But in + the case of clust index 2 pages are allocated and as one is + covered in the calculation as part of table->indexes.count we + take care of the other page by adding 1. */ + ulint space_size = table->indexes.count + + FIL_IBD_FILE_INITIAL_SIZE + 1; + + if (has_internal_doc_id) { + /* Since aux tables are created for fts indexes and + they use seperate tablespaces. */ + space_size -= ib_vector_size(table->fts->indexes); + } + + fil_reinit_space_header_for_table(table, space_size, trx); + } + + DBUG_EXECUTE_IF("ib_trunc_crash_with_intermediate_log_checkpoint", + log_buffer_flush_to_disk(); + os_thread_sleep(2000000); + log_checkpoint(TRUE, TRUE); + os_thread_sleep(1000000); + DBUG_SUICIDE();); + + DBUG_EXECUTE_IF("ib_trunc_crash_drop_reinit_done_create_to_start", + log_buffer_flush_to_disk(); + os_thread_sleep(2000000); + DBUG_SUICIDE();); + + /* Step-10: Re-create new indexes. */ + if (!dict_table_is_temporary(table)) { + + CreateIndex createIndex(table, no_redo); + + err = SysIndexIterator().for_each(createIndex); + + if (err != DB_SUCCESS) { + + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, true, true); + + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } + + /* Done with index truncation, release index tree locks, + subsequent work relates to table level metadata change */ + dict_table_x_unlock_indexes(table); + + if (has_internal_doc_id) { + + err = row_truncate_fts(table, new_id, trx); + + if (err != DB_SUCCESS) { + + row_truncate_rollback( + table, trx, new_id, has_internal_doc_id, + no_redo, true, false); + + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } + + /* Step-11: Update new table-id to in-memory cache (dictionary), + on-disk (INNODB_SYS_TABLES). INNODB_SYS_INDEXES also needs to + be updated to reflect updated root-page-no of new index created + and updated table-id. */ + if (dict_table_is_temporary(table)) { + + dict_table_change_id_in_cache(table, new_id); + err = DB_SUCCESS; + + } else { + + /* If this fails then we are in an inconsistent state and + the results are undefined. */ + ut_ad(old_space == table->space); + + err = row_truncate_update_system_tables( + table, new_id, has_internal_doc_id, no_redo, trx); + + if (err != DB_SUCCESS) { + return(row_truncate_complete( + table, trx, fsp_flags, logger, err)); + } + } + + DBUG_EXECUTE_IF("ib_trunc_crash_on_updating_dict_sys_info", + log_buffer_flush_to_disk(); + os_thread_sleep(2000000); + DBUG_SUICIDE();); + + /* Step-12: Cleanup Stage. Reset auto-inc value to 1. + Release all the locks. + Commit the transaction. Update trx operation state. */ + dict_table_autoinc_lock(table); + dict_table_autoinc_initialize(table, 1); + dict_table_autoinc_unlock(table); + + if (trx_is_started(trx)) { + + trx_commit_for_mysql(trx); + } + + return(row_truncate_complete(table, trx, fsp_flags, logger, err)); +} + /** Fix the table truncate by applying information parsed from TRUNCATE log. Fix-up includes re-creating table (drop and re-create indexes) diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 342f0d222e0..171e06894ca 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -286,6 +286,34 @@ row_upd_check_references_constraints( FALSE, FALSE, DICT_ERR_IGNORE_NONE); } + /* dict_operation_lock is held both here + (UPDATE or DELETE with FOREIGN KEY) and by TRUNCATE + TABLE operations. + If a TRUNCATE TABLE operation is in progress, + there can be 2 possible conditions: + 1) row_truncate_table_for_mysql() is not yet called. + 2) Truncate releases dict_operation_lock + during eviction of pages from buffer pool + for a file-per-table tablespace. + + In case of (1), truncate will wait for FK operation + to complete. + In case of (2), truncate will be rolled forward even + if it is interrupted. So if the foreign table is + undergoing a truncate, ignore the FK check. */ + + if (foreign_table) { + mutex_enter(&fil_system->mutex); + const fil_space_t* space = fil_space_get_by_id( + foreign_table->space); + const bool being_truncated = space + && space->is_being_truncated; + mutex_exit(&fil_system->mutex); + if (being_truncated) { + continue; + } + } + /* NOTE that if the thread ends up waiting for a lock we will release dict_operation_lock temporarily! But the counter on the table protects 'foreign' from diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 7ebe0015ffe..10bd308ec53 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -152,6 +152,9 @@ my_bool srv_read_only_mode; /** store to its own file each table created by an user; data dictionary tables are in the system tablespace 0 */ my_bool srv_file_per_table; +/** whether to use the MySQL 5.7 WL#6501 TRUNCATE TABLE implementation +that does not work with backup */ +my_bool srv_57_truncate; /** The file format to use on new *.ibd files. */ ulint srv_file_format; /** Whether to check file format during startup. A value of diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index ca0e1472aed..c39a5ea1937 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1393,10 +1393,17 @@ srv_prepare_to_delete_redo_log_files( ulint pending_io = 0; ulint count = 0; - if ((log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) - != LOG_HEADER_FORMAT_CURRENT - || log_sys->log.subformat != 1) { - srv_log_file_size = 0; + if (srv_57_truncate) { + if ((log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) + != LOG_HEADER_FORMAT_10_2) { + srv_log_file_size = 0; + } + } else { + if ((log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) + != LOG_HEADER_FORMAT_10_3 + || log_sys->log.subformat != 1) { + srv_log_file_size = 0; + } } do { @@ -1417,7 +1424,7 @@ srv_prepare_to_delete_redo_log_files( if (srv_log_file_size == 0) { info << ((log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) - < LOG_HEADER_FORMAT_CURRENT + < LOG_HEADER_FORMAT_10_3 ? "Upgrading redo log: " : "Downgrading redo log: "); } else if (n_files != srv_n_log_files @@ -2392,11 +2399,16 @@ files_checked: } else if (srv_log_file_size_requested == srv_log_file_size && srv_n_log_files_found == srv_n_log_files && log_sys->log.format - == (srv_encrypt_log - ? LOG_HEADER_FORMAT_CURRENT - | LOG_HEADER_FORMAT_ENCRYPTED - : LOG_HEADER_FORMAT_CURRENT) - && log_sys->log.subformat == 1) { + == (srv_57_truncate + ? (srv_encrypt_log + ? LOG_HEADER_FORMAT_10_2 + | LOG_HEADER_FORMAT_ENCRYPTED + : LOG_HEADER_FORMAT_10_2) + : (srv_encrypt_log + ? LOG_HEADER_FORMAT_10_3 + | LOG_HEADER_FORMAT_ENCRYPTED + : LOG_HEADER_FORMAT_10_3)) + && log_sys->log.subformat == !srv_57_truncate) { /* No need to add or remove encryption, upgrade, downgrade, or resize. */ } else { diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 1c55106f016..a50cdbaad6f 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1938,6 +1938,7 @@ trx_undo_report_rename(trx_t* trx, const dict_table_t* table) ut_ad(!trx->read_only); ut_ad(trx->id); ut_ad(!table->is_temporary()); + ut_ad(!srv_57_truncate); trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; trx_undo_t** pundo = &trx->rsegs.m_redo.insert_undo; -- cgit v1.2.1 From 4de0d920bede330ddf7790d0aee4bf90a00122ae Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 11 Oct 2018 13:39:53 +0400 Subject: MDEV-17411 Wrong WHERE optimization with simple CASE and searched CASE --- mysql-test/main/case.result | 27 +++++++++++++++++++++++++++ mysql-test/main/case.test | 22 ++++++++++++++++++++++ sql/item.h | 9 +++++++++ sql/item_cmpfunc.cc | 5 +---- sql/item_cmpfunc.h | 2 ++ sql/item_func.cc | 5 +---- sql/item_func.h | 5 ++++- 7 files changed, 66 insertions(+), 9 deletions(-) diff --git a/mysql-test/main/case.result b/mysql-test/main/case.result index 1fd1ad86a8e..926ac000eb0 100644 --- a/mysql-test/main/case.result +++ b/mysql-test/main/case.result @@ -546,5 +546,32 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 'a' DROP TABLE t1; # +# MDEV-17411 Wrong WHERE optimization with simple CASE and searched CASE +# +CREATE TABLE t1 (a INT, b INT, KEY(a)); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +SELECT * FROM t1 WHERE CASE a WHEN b THEN 1 END=1; +a b +1 1 +2 2 +3 3 +SELECT * FROM t1 WHERE CASE WHEN a THEN b ELSE 1 END=3; +a b +3 3 +SELECT * FROM t1 WHERE +CASE a WHEN b THEN 1 END=1 AND +CASE WHEN a THEN b ELSE 1 END=3; +a b +3 3 +EXPLAIN EXTENDED +SELECT * FROM t1 WHERE +CASE a WHEN b THEN 1 END=1 AND +CASE WHEN a THEN b ELSE 1 END=3; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (case `test`.`t1`.`a` when `test`.`t1`.`b` then 1 end) = 1 and (case when `test`.`t1`.`a` then `test`.`t1`.`b` else 1 end) = 3 +DROP TABLE t1; +# # End of 10.3 test # diff --git a/mysql-test/main/case.test b/mysql-test/main/case.test index d7dac112b3b..78d5b3a5951 100644 --- a/mysql-test/main/case.test +++ b/mysql-test/main/case.test @@ -390,6 +390,28 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='a' AND CASE 'a' WHEN 'a' THEN 'a' ELS DROP TABLE t1; + +--echo # +--echo # MDEV-17411 Wrong WHERE optimization with simple CASE and searched CASE +--echo # + +CREATE TABLE t1 (a INT, b INT, KEY(a)); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +SELECT * FROM t1 WHERE CASE a WHEN b THEN 1 END=1; +SELECT * FROM t1 WHERE CASE WHEN a THEN b ELSE 1 END=3; + +SELECT * FROM t1 WHERE + CASE a WHEN b THEN 1 END=1 AND + CASE WHEN a THEN b ELSE 1 END=3; + +EXPLAIN EXTENDED +SELECT * FROM t1 WHERE + CASE a WHEN b THEN 1 END=1 AND + CASE WHEN a THEN b ELSE 1 END=3; + +DROP TABLE t1; + + --echo # --echo # End of 10.3 test --echo # diff --git a/sql/item.h b/sql/item.h index 6823d58a94c..d743cf6c19c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2211,6 +2211,15 @@ protected: } return true; } + bool eq(const Item_args *other, bool binary_cmp) const + { + for (uint i= 0; i < arg_count ; i++) + { + if (!args[i]->eq(other->args[i], binary_cmp)) + return false; + } + return true; + } public: Item_args(void) :args(NULL), arg_count(0) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 4a7a44b3399..92f1391c9f8 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1813,10 +1813,7 @@ bool Item_func_opt_neg::eq(const Item *item, bool binary_cmp) const return 0; if (negated != ((Item_func_opt_neg *) item_func)->negated) return 0; - for (uint i=0; i < arg_count ; i++) - if (!args[i]->eq(item_func->arguments()[i], binary_cmp)) - return 0; - return 1; + return Item_args::eq(item_func, binary_cmp); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index b34bf1dde19..60b56090a23 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -2154,6 +2154,7 @@ public: DBUG_ASSERT(arg_count >= 2); reorder_args(0); } + enum Functype functype() const { return CASE_SEARCHED_FUNC; } void print(String *str, enum_query_type query_type); bool fix_length_and_dec(); Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) @@ -2206,6 +2207,7 @@ public: Predicant_to_list_comparator::cleanup(); DBUG_VOID_RETURN; } + enum Functype functype() const { return CASE_SIMPLE_FUNC; } void print(String *str, enum_query_type query_type); bool fix_length_and_dec(); Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond); diff --git a/sql/item_func.cc b/sql/item_func.cc index 3dcfe4fbce8..c5ac97f2905 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -647,10 +647,7 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const (func_type == Item_func::FUNC_SP && my_strcasecmp(system_charset_info, func_name(), item_func->func_name()))) return 0; - for (uint i=0; i < arg_count ; i++) - if (!args[i]->eq(item_func->args[i], binary_cmp)) - return 0; - return 1; + return Item_args::eq(item_func, binary_cmp); } diff --git a/sql/item_func.h b/sql/item_func.h index 1d19c7a43f1..fd789ffdc51 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -76,7 +76,10 @@ public: SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC, EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC, NEG_FUNC, GSYSVAR_FUNC, IN_OPTIMIZER_FUNC, DYNCOL_FUNC, - JSON_EXTRACT_FUNC }; + JSON_EXTRACT_FUNC, + CASE_SEARCHED_FUNC, // Used by ColumnStore/Spider + CASE_SIMPLE_FUNC // Used by ColumnStore/spider + }; enum Type type() const { return FUNC_ITEM; } virtual enum Functype functype() const { return UNKNOWN_FUNC; } Item_func(THD *thd): Item_func_or_sum(thd) -- cgit v1.2.1 From 6319c0b5417f2e7dd22ab198ae62131fd7ed4d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 11 Oct 2018 15:10:13 +0300 Subject: MDEV-13564: Replace innodb_unsafe_truncate with innodb_safe_truncate Rename the 10.2-specific configuration option innodb_unsafe_truncate to innodb_safe_truncate, and invert its value. The default (for now) is innodb_safe_truncate=OFF, to avoid disrupting users with an undo and redo log format change within a Generally Available (GA) release series. --- .../suite/gcol/t/innodb_virtual_debug_purge.opt | 2 +- mysql-test/suite/innodb/t/alter_copy.opt | 2 +- mysql-test/suite/innodb/t/alter_crash.opt | 2 +- .../suite/innodb/t/drop_table_background.opt | 2 +- mysql-test/suite/innodb/t/rename_table_debug.opt | 2 +- mysql-test/suite/innodb/t/truncate.opt | 2 +- mysql-test/suite/innodb/t/truncate_crash.opt | 2 +- mysql-test/suite/innodb/t/truncate_foreign.opt | 2 +- mysql-test/suite/innodb/t/truncate_missing.opt | 2 +- mysql-test/suite/innodb_zip/t/restart.opt | 2 +- .../suite/mariabackup/truncate_during_backup.opt | 2 +- mysql-test/suite/sys_vars/r/sysvars_innodb.result | 28 +++++++++++----------- storage/innobase/handler/ha_innodb.cc | 10 ++++---- storage/innobase/include/srv0srv.h | 6 ++--- storage/innobase/log/log0log.cc | 20 ++++++++-------- storage/innobase/log/log0recv.cc | 2 +- storage/innobase/row/row0mysql.cc | 2 +- storage/innobase/srv/srv0srv.cc | 6 ++--- storage/innobase/srv/srv0start.cc | 20 ++++++++-------- storage/innobase/trx/trx0rec.cc | 2 +- 20 files changed, 59 insertions(+), 59 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 index 20a4e60b8ec..9622465d71f 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.opt +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.opt @@ -1 +1 @@ ---skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/innodb/t/alter_copy.opt b/mysql-test/suite/innodb/t/alter_copy.opt index e76044be888..9622465d71f 100644 --- a/mysql-test/suite/innodb/t/alter_copy.opt +++ b/mysql-test/suite/innodb/t/alter_copy.opt @@ -1 +1 @@ ---loose-skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/innodb/t/alter_crash.opt b/mysql-test/suite/innodb/t/alter_crash.opt index 96710441921..0e92a05802e 100644 --- a/mysql-test/suite/innodb/t/alter_crash.opt +++ b/mysql-test/suite/innodb/t/alter_crash.opt @@ -1,2 +1,2 @@ --loose-innodb-sys-tables ---loose-skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/innodb/t/drop_table_background.opt b/mysql-test/suite/innodb/t/drop_table_background.opt index e76044be888..9622465d71f 100644 --- a/mysql-test/suite/innodb/t/drop_table_background.opt +++ b/mysql-test/suite/innodb/t/drop_table_background.opt @@ -1 +1 @@ ---loose-skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/innodb/t/rename_table_debug.opt b/mysql-test/suite/innodb/t/rename_table_debug.opt index e76044be888..9622465d71f 100644 --- a/mysql-test/suite/innodb/t/rename_table_debug.opt +++ b/mysql-test/suite/innodb/t/rename_table_debug.opt @@ -1 +1 @@ ---loose-skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/innodb/t/truncate.opt b/mysql-test/suite/innodb/t/truncate.opt index e76044be888..9622465d71f 100644 --- a/mysql-test/suite/innodb/t/truncate.opt +++ b/mysql-test/suite/innodb/t/truncate.opt @@ -1 +1 @@ ---loose-skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/innodb/t/truncate_crash.opt b/mysql-test/suite/innodb/t/truncate_crash.opt index e76044be888..9622465d71f 100644 --- a/mysql-test/suite/innodb/t/truncate_crash.opt +++ b/mysql-test/suite/innodb/t/truncate_crash.opt @@ -1 +1 @@ ---loose-skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/innodb/t/truncate_foreign.opt b/mysql-test/suite/innodb/t/truncate_foreign.opt index e76044be888..9622465d71f 100644 --- a/mysql-test/suite/innodb/t/truncate_foreign.opt +++ b/mysql-test/suite/innodb/t/truncate_foreign.opt @@ -1 +1 @@ ---loose-skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/innodb/t/truncate_missing.opt b/mysql-test/suite/innodb/t/truncate_missing.opt index e76044be888..9622465d71f 100644 --- a/mysql-test/suite/innodb/t/truncate_missing.opt +++ b/mysql-test/suite/innodb/t/truncate_missing.opt @@ -1 +1 @@ ---loose-skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/innodb_zip/t/restart.opt b/mysql-test/suite/innodb_zip/t/restart.opt index fd89db6cc1d..8101a8573fc 100644 --- a/mysql-test/suite/innodb_zip/t/restart.opt +++ b/mysql-test/suite/innodb_zip/t/restart.opt @@ -1,4 +1,4 @@ --loose-innodb-sys-tables --loose-innodb-sys-tablespaces --loose-innodb-sys-datafiles ---loose-skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/mariabackup/truncate_during_backup.opt b/mysql-test/suite/mariabackup/truncate_during_backup.opt index e76044be888..9622465d71f 100644 --- a/mysql-test/suite/mariabackup/truncate_during_backup.opt +++ b/mysql-test/suite/mariabackup/truncate_during_backup.opt @@ -1 +1 @@ ---loose-skip-innodb-unsafe-truncate +--loose-innodb-safe-truncate=1 diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 0673de0054a..a2b82df3dbc 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2400,6 +2400,20 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME INNODB_SAFE_TRUNCATE +SESSION_VALUE NULL +GLOBAL_VALUE OFF +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE OFF +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Use backup-safe TRUNCATE TABLE and crash-safe RENAME (incompatible with older MariaDB 10.2; OFF 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_SAVED_PAGE_NUMBER_DEBUG SESSION_VALUE NULL GLOBAL_VALUE 0 @@ -2974,20 +2988,6 @@ 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/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 26e169b1ec3..e7ec8488d45 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13452,7 +13452,7 @@ int ha_innobase::truncate() update_thd(); - if (srv_57_truncate) { + if (!srv_safe_truncate) { if (!trx_is_started(m_prebuilt->trx)) { ++m_prebuilt->trx->will_lock; } @@ -20694,10 +20694,10 @@ 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, +static MYSQL_SYSVAR_BOOL(safe_truncate, srv_safe_truncate, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, - "Use backup-unsafe TRUNCATE TABLE for compatibility with xtrabackup (on by default)", - NULL, NULL, TRUE); + "Use backup-safe TRUNCATE TABLE and crash-safe RENAME (incompatible with older MariaDB 10.2; OFF by default)", + NULL, NULL, FALSE); static MYSQL_SYSVAR_BOOL(cmp_per_index_enabled, srv_cmp_per_index_enabled, PLUGIN_VAR_OPCMDARG, @@ -21078,7 +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(safe_truncate), MYSQL_SYSVAR(io_capacity), MYSQL_SYSVAR(io_capacity_max), MYSQL_SYSVAR(page_cleaners), diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index f40cbf7f730..832a67539da 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -256,9 +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; +/** whether to use backup-safe TRUNCATE and crash-safe RENAME +instead of the MySQL 5.7 WL#6501 TRUNCATE TABLE implementation */ +extern my_bool srv_safe_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 b7d39440c75..8fa8662ca31 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -790,15 +790,15 @@ log_init(ulint n_files) log_group_t* group = &log_sys->log; group->n_files = n_files; - 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->subformat = srv_safe_truncate; + if (srv_safe_truncate) { group->format = srv_encrypt_log ? LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED : LOG_HEADER_FORMAT_10_3; + } else { + group->format = srv_encrypt_log + ? LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED + : LOG_HEADER_FORMAT_10_2; } group->file_size = srv_log_file_size; group->state = LOG_GROUP_OK; @@ -881,15 +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) - == (srv_57_truncate - ? LOG_HEADER_FORMAT_10_2 - : LOG_HEADER_FORMAT_10_3)); + == (srv_safe_truncate + ? LOG_HEADER_FORMAT_10_3 + : LOG_HEADER_FORMAT_10_2)); 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, !srv_57_truncate); + mach_write_to_4(buf + LOG_HEADER_SUBFORMAT, srv_safe_truncate); mach_write_to_8(buf + LOG_HEADER_START_LSN, start_lsn); strcpy(reinterpret_cast(buf) + LOG_HEADER_CREATOR, LOG_HEADER_CREATOR_CURRENT); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 2d2d9f2d674..880935e304e 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3769,7 +3769,7 @@ recv_recovery_rollback_active(void) /* Drop partially created indexes. */ row_merge_drop_temp_indexes(); /* Drop garbage tables. */ - if (!srv_57_truncate) + if (srv_safe_truncate) row_mysql_drop_garbage_tables(); /* Drop any auxiliary tables that were not dropped when the diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 5f558203ca4..02a71d2fa63 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() && !srv_57_truncate) { + if (!table->is_temporary() && srv_safe_truncate) { err = trx_undo_report_rename(trx, table); if (err != DB_SUCCESS) { diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 10bd308ec53..0aebdb1cfd3 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -152,9 +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; +/** whether to use backup-safe TRUNCATE and crash-safe RENAME +instead of the MySQL 5.7 WL#6501 TRUNCATE TABLE implementation */ +my_bool srv_safe_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 c39a5ea1937..9349220234e 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1393,15 +1393,15 @@ srv_prepare_to_delete_redo_log_files( ulint pending_io = 0; ulint count = 0; - if (srv_57_truncate) { + if (srv_safe_truncate) { if ((log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) - != LOG_HEADER_FORMAT_10_2) { + != LOG_HEADER_FORMAT_10_3 + || log_sys->log.subformat != 1) { 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) { + != LOG_HEADER_FORMAT_10_2) { srv_log_file_size = 0; } } @@ -2399,16 +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_57_truncate + == (srv_safe_truncate ? (srv_encrypt_log - ? LOG_HEADER_FORMAT_10_2 + ? LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED - : LOG_HEADER_FORMAT_10_2) + : LOG_HEADER_FORMAT_10_3) : (srv_encrypt_log - ? LOG_HEADER_FORMAT_10_3 + ? LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED - : LOG_HEADER_FORMAT_10_3)) - && log_sys->log.subformat == !srv_57_truncate) { + : LOG_HEADER_FORMAT_10_2)) + && log_sys->log.subformat == srv_safe_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 a50cdbaad6f..9f47fd89945 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1938,7 +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); + ut_ad(srv_safe_truncate); trx_rseg_t* rseg = trx->rsegs.m_redo.rseg; trx_undo_t** pundo = &trx->rsegs.m_redo.insert_undo; -- cgit v1.2.1 From b8944e897298968a0bc31119bc975ef472bdb820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 11 Oct 2018 22:47:42 +0300 Subject: Fix a sign mismatch --- storage/innobase/srv/srv0start.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 9349220234e..a360a6ea50e 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2408,7 +2408,7 @@ files_checked: ? LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED : LOG_HEADER_FORMAT_10_2)) - && log_sys->log.subformat == srv_safe_truncate) { + && log_sys->log.subformat == !!srv_safe_truncate) { /* No need to add or remove encryption, upgrade, downgrade, or resize. */ } else { -- cgit v1.2.1 From 81a5b6ccd531e802bbb0f2034189095d2196de8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 11 Oct 2018 22:48:19 +0300 Subject: MDEV-17433 Allow InnoDB start up with empty ib_logfile0 from mariabackup --prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A prepared backup from Mariabackup does not really need to contain any redo log file, because all log will have been applied to the data files. When the user copies a prepared backup to a data directory (overwriting existing files), it could happen that the data directory already contained redo log files from the past. mariabackup --copy-back) would delete the old redo log files, but a user’s own copying script might not do that. To prevent corruption caused by mixing an old redo log file with data files from a backup, starting with MDEV-13311, Mariabackup would create a zero-length ib_logfile0 that would prevent startup. Actually, there is no need to prevent InnoDB from starting up when a single zero-length file ib_logfile0 is present. Only if there exist multiple data files of different lengths, then we should refuse to start up due to inconsistency. A single zero-length ib_logfile0 should be treated as if the log files were missing: create new log files according to the configuration. open_log_file(): Remove. There is no need to open the log files at this point, because os_file_get_status() already determined the size of the file. innobase_start_or_create_for_mysql(): Move the creation of new log files a little later, not when finding out that the first log file does not exist, but after finding out that it does not exist or it exists as a zero-length file. --- mysql-test/suite/innodb/r/log_file_size.result | 2 +- mysql-test/suite/innodb/t/log_file_size.test | 2 +- storage/innobase/srv/srv0start.cc | 114 ++++++++++--------------- 3 files changed, 45 insertions(+), 73 deletions(-) diff --git a/mysql-test/suite/innodb/r/log_file_size.result b/mysql-test/suite/innodb/r/log_file_size.result index e049b34ad81..89d5c6ac4d6 100644 --- a/mysql-test/suite/innodb/r/log_file_size.result +++ b/mysql-test/suite/innodb/r/log_file_size.result @@ -3,7 +3,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -FOUND 1 /InnoDB: Log file .*ib_logfile0 size 0 is too small/ in mysqld.1.err +FOUND 1 /InnoDB: Log file .*ib_logfile1 is of different size .* bytes than other log files 0 bytes!/ in mysqld.1.err CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK diff --git a/mysql-test/suite/innodb/t/log_file_size.test b/mysql-test/suite/innodb/t/log_file_size.test index 44cb155c7d9..1e6c7cd4d00 100644 --- a/mysql-test/suite/innodb/t/log_file_size.test +++ b/mysql-test/suite/innodb/t/log_file_size.test @@ -43,7 +43,7 @@ eval $check_no_innodb; --move_file $MYSQLD_DATADIR/ib_logfile.old $MYSQLD_DATADIR/ib_logfile.0 --source include/shutdown_mysqld.inc let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; -let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile0 size 0 is too small; +let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile1 is of different size .* bytes than other log files 0 bytes!; --source include/search_pattern_in_file.inc --source include/start_mysqld.inc CHECK TABLE t1; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index a360a6ea50e..c6551595a08 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -570,34 +570,6 @@ create_log_files_rename( return(err); } -/*********************************************************************//** -Opens a log file. -@return DB_SUCCESS or error code */ -static MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t -open_log_file( -/*==========*/ - pfs_os_file_t* file, /*!< out: file handle */ - const char* name, /*!< in: log file name */ - os_offset_t* size) /*!< out: file size */ -{ - bool ret; - - *file = os_file_create(innodb_log_file_key, name, - OS_FILE_OPEN, OS_FILE_AIO, - OS_LOG_FILE, srv_read_only_mode, &ret); - if (!ret) { - ib::error() << "Unable to open '" << name << "'"; - return(DB_ERROR); - } - - *size = os_file_get_size(*file); - - ret = os_file_close(*file); - ut_a(ret); - return(DB_SUCCESS); -} - /*********************************************************************//** Create undo tablespace. @return DB_SUCCESS or error code */ @@ -1975,8 +1947,9 @@ innobase_start_or_create_for_mysql() return(srv_init_abort(err)); } } else { + srv_log_file_size = 0; + for (i = 0; i < SRV_N_LOG_FILES_MAX; i++) { - os_offset_t size; os_file_stat_t stat_info; sprintf(logfilename + dirnamelen, @@ -1994,40 +1967,6 @@ innobase_start_or_create_for_mysql() == SRV_OPERATION_RESTORE_EXPORT) { return(DB_SUCCESS); } - if (flushed_lsn - < static_cast(1000)) { - ib::error() - << "Cannot create" - " log files because" - " data files are" - " corrupt or the" - " database was not" - " shut down cleanly" - " after creating" - " the data files."; - return(srv_init_abort( - DB_ERROR)); - } - - err = create_log_files( - logfilename, dirnamelen, - flushed_lsn, logfile0); - - if (err == DB_SUCCESS) { - err = create_log_files_rename( - logfilename, - dirnamelen, - flushed_lsn, logfile0); - } - - if (err != DB_SUCCESS) { - return(srv_init_abort(err)); - } - - /* Suppress the message about - crash recovery. */ - flushed_lsn = log_get_lsn(); - goto files_checked; } /* opened all files */ @@ -2038,12 +1977,7 @@ innobase_start_or_create_for_mysql() return(srv_init_abort(DB_ERROR)); } - err = open_log_file(&files[i], logfilename, &size); - - if (err != DB_SUCCESS) { - return(srv_init_abort(err)); - } - + const os_offset_t size = stat_info.size; ut_a(size != (os_offset_t) -1); if (size & (OS_FILE_LOG_BLOCK_SIZE - 1)) { @@ -2068,8 +2002,13 @@ innobase_start_or_create_for_mysql() /* The first log file must consist of at least the following 512-byte pages: header, checkpoint page 1, empty, - checkpoint page 2, redo log page(s) */ - if (size <= OS_FILE_LOG_BLOCK_SIZE * 4) { + checkpoint page 2, redo log page(s). + + Mariabackup --prepare would create an + empty ib_logfile0. Tolerate it if there + are no other ib_logfile* files. */ + if ((size != 0 || i != 0) + && size <= OS_FILE_LOG_BLOCK_SIZE * 4) { ib::error() << "Log file " << logfilename << " size " << size << " is too small"; @@ -2086,6 +2025,39 @@ innobase_start_or_create_for_mysql() } } + if (srv_log_file_size == 0) { + if (flushed_lsn < lsn_t(1000)) { + ib::error() + << "Cannot create log files because" + " data files are corrupt or the" + " database was not shut down cleanly" + " after creating the data files."; + return srv_init_abort(DB_ERROR); + } + + strcpy(logfilename + dirnamelen, "ib_logfile0"); + srv_log_file_size = srv_log_file_size_requested; + + err = create_log_files( + logfilename, dirnamelen, + flushed_lsn, logfile0); + + if (err == DB_SUCCESS) { + err = create_log_files_rename( + logfilename, dirnamelen, + flushed_lsn, logfile0); + } + + if (err != DB_SUCCESS) { + return(srv_init_abort(err)); + } + + /* Suppress the message about + crash recovery. */ + flushed_lsn = log_get_lsn(); + goto files_checked; + } + srv_n_log_files_found = i; /* Create the in-memory file space objects. */ -- cgit v1.2.1 From ce643ddac78ce66cdef9e4c0164ce7f8fbcf2da0 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sun, 14 Jan 2018 15:00:36 +1100 Subject: MDEV-8765: mysqldump -use utf8mb4 by default Bump mysqldump to a version greater than that on the 10.3 branch. --- client/mysqldump.c | 2 +- include/my_global.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index a346c295d29..a2ed3c0504c 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -39,7 +39,7 @@ ** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov */ -#define DUMP_VERSION "10.16" +#define DUMP_VERSION "10.17" #include #include diff --git a/include/my_global.h b/include/my_global.h index 10704a89842..7904eed3dfc 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1054,7 +1054,9 @@ typedef ulong myf; /* Type of MyFlags in my_funcs */ #include -#ifdef HAVE_CHARSET_utf8 +#ifdef HAVE_CHARSET_utf8mb4 +#define MYSQL_UNIVERSAL_CLIENT_CHARSET "utf8mb4" +#elif defined(HAVE_CHARSET_utf8) #define MYSQL_UNIVERSAL_CLIENT_CHARSET "utf8" #else #define MYSQL_UNIVERSAL_CLIENT_CHARSET MYSQL_DEFAULT_CHARSET_NAME -- cgit v1.2.1 From 6120ae4acafb23badecc623e33797949e3f6fbbb Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 12 Oct 2018 06:15:21 +0400 Subject: Adjusting old tests and adding new tests for "MDEV-8765: mysqldump -use utf8mb4 by default" --- mysql-test/main/mysqldump-max.result | 4 +- mysql-test/main/mysqldump-max.test | 2 + mysql-test/main/mysqldump-utf8mb4.result | 86 ++++++++++++++++++++++ mysql-test/main/mysqldump-utf8mb4.test | 49 ++++++++++++ mysql-test/main/mysqldump.result | 82 ++++++++++----------- mysql-test/main/mysqldump.test | 2 + mysql-test/main/openssl_1.result | 6 +- mysql-test/main/openssl_1.test | 3 + .../compat/oracle/r/sp-package-mysqldump.result | 2 +- .../compat/oracle/t/sp-package-mysqldump.test | 1 + 10 files changed, 190 insertions(+), 47 deletions(-) create mode 100644 mysql-test/main/mysqldump-utf8mb4.result create mode 100644 mysql-test/main/mysqldump-utf8mb4.test diff --git a/mysql-test/main/mysqldump-max.result b/mysql-test/main/mysqldump-max.result index b75eb969da6..f936184849f 100644 --- a/mysql-test/main/mysqldump-max.result +++ b/mysql-test/main/mysqldump-max.result @@ -81,7 +81,7 @@ id name /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -178,7 +178,7 @@ INSERT IGNORE INTO `t6` VALUES (1,'first value'),(2,'first value'),(3,'first va /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; diff --git a/mysql-test/main/mysqldump-max.test b/mysql-test/main/mysqldump-max.test index c0596f27e4f..4aadb09de53 100644 --- a/mysql-test/main/mysqldump-max.test +++ b/mysql-test/main/mysqldump-max.test @@ -1,3 +1,5 @@ +--source include/have_utf8mb4.inc + # Embedded server doesn't support external clients --source include/not_embedded.inc --source include/have_innodb.inc diff --git a/mysql-test/main/mysqldump-utf8mb4.result b/mysql-test/main/mysqldump-utf8mb4.result new file mode 100644 index 00000000000..3bafd6da6c9 --- /dev/null +++ b/mysql-test/main/mysqldump-utf8mb4.result @@ -0,0 +1,86 @@ +SET NAMES utf8mb4; +# +# MDEV-8765 mysqldump silently corrupts 4-byte UTF-8 data +# +CREATE TABLE t1 ( +point VARCHAR(10) PRIMARY KEY, +data VARCHAR(10), +comment VARCHAR(64) +) CHARACTER SET utf8mb4; +INSERT INTO t1 VALUES ('01f300', UNHEX('f09f8c80'), 'U+1F300 CYCLONE'); +---- +Testing XML format output +---- + + + + + + + + + + + + 01f300 + 🌀 + U+1F300 CYCLONE + + + + +---- +Testing text format output +---- + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `t1` ( + `point` varchar(10) NOT NULL, + `data` varchar(10) DEFAULT NULL, + `comment` varchar(64) DEFAULT NULL, + PRIMARY KEY (`point`) +); +/*!40101 SET character_set_client = @saved_cs_client */; + +LOCK TABLES `t1` WRITE; +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +INSERT INTO `t1` VALUES ('01f300','🌀','U+1F300 CYCLONE'); +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE t1; +---- +Testing text format dump/restore +---- +CREATE TABLE t1 ( +point VARCHAR(10) PRIMARY KEY, +data VARCHAR(10), +comment VARCHAR(64) +) CHARACTER SET utf8mb4; +INSERT INTO t1 VALUES ('01f300', UNHEX('f09f8c80'), 'U+1F300 CYCLONE'); +DROP TABLE t1; +SELECT * FROM t1; +point data comment +01f300 🌀 U+1F300 CYCLONE +DROP TABLE t1; diff --git a/mysql-test/main/mysqldump-utf8mb4.test b/mysql-test/main/mysqldump-utf8mb4.test new file mode 100644 index 00000000000..f8512c9bd7b --- /dev/null +++ b/mysql-test/main/mysqldump-utf8mb4.test @@ -0,0 +1,49 @@ +--source include/have_utf8mb4.inc +--source include/not_embedded.inc + +SET NAMES utf8mb4; + +--echo # +--echo # MDEV-8765 mysqldump silently corrupts 4-byte UTF-8 data +--echo # + +CREATE TABLE t1 ( + point VARCHAR(10) PRIMARY KEY, + data VARCHAR(10), + comment VARCHAR(64) +) CHARACTER SET utf8mb4; +INSERT INTO t1 VALUES ('01f300', UNHEX('f09f8c80'), 'U+1F300 CYCLONE'); + +--echo ---- +--echo Testing XML format output +--echo ---- + +--exec $MYSQL_DUMP --skip-create-options --skip-comments -X test t1 + + +--echo ---- +--echo Testing text format output +--echo ---- + +--exec $MYSQL_DUMP --skip-create-options --skip-comments test t1 +DROP TABLE t1; + + +--echo ---- +--echo Testing text format dump/restore +--echo ---- + +--let $file = $MYSQLTEST_VARDIR/tmp/mysqldump-utf8mb4.sql + +CREATE TABLE t1 ( + point VARCHAR(10) PRIMARY KEY, + data VARCHAR(10), + comment VARCHAR(64) +) CHARACTER SET utf8mb4; +INSERT INTO t1 VALUES ('01f300', UNHEX('f09f8c80'), 'U+1F300 CYCLONE'); + +--exec $MYSQL_DUMP test t1 > $file +DROP TABLE t1; +--exec $MYSQL test < $file +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result index 11e46657888..1366f9bdd12 100644 --- a/mysql-test/main/mysqldump.result +++ b/mysql-test/main/mysqldump.result @@ -91,7 +91,7 @@ INSERT INTO `t1` VALUES (1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -202,7 +202,7 @@ INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -305,7 +305,7 @@ create table t1(a int); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -364,7 +364,7 @@ set global sql_mode='ANSI_QUOTES'; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -429,7 +429,7 @@ insert into t1 values (1),(2),(3); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='' */; @@ -461,7 +461,7 @@ drop table t1; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -487,7 +487,7 @@ create database mysqldump_test_db character set latin2 collate latin2_bin; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -521,7 +521,7 @@ INSERT INTO t1 VALUES (_latin1 ' /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -639,7 +639,7 @@ INSERT INTO t2 VALUES (4),(5),(6); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -680,7 +680,7 @@ INSERT INTO `t1` VALUES (0x602010000280100005E71A); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -721,7 +721,7 @@ INSERT INTO t1 VALUES (4),(5),(6); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -755,7 +755,7 @@ UNLOCK TABLES; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -1124,7 +1124,7 @@ insert into t1 (F_8d3bba7425e7c98c50f52ca1b52d3735) values (1); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -1493,7 +1493,7 @@ INSERT INTO t1 VALUES (1),(2),(3); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -1543,7 +1543,7 @@ INSERT INTO t2 VALUES (1), (2); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -1578,7 +1578,7 @@ CREATE TABLE `t2` ( /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -1726,7 +1726,7 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; @@ -1757,7 +1757,7 @@ UNLOCK TABLES; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -1874,7 +1874,7 @@ create table t3(a int); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -1923,7 +1923,7 @@ mysqldump: Got error: 1064: "You have an error in your SQL syntax; check the man /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -1993,7 +1993,7 @@ UNLOCK TABLES; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -2047,7 +2047,7 @@ create view v2 as select * from t2 where a like 'a%' with check option; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -2143,7 +2143,7 @@ create view v1 as select * from t1; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -2215,7 +2215,7 @@ create view v2 as select * from t2 where a like 'a%' with check option; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -2282,7 +2282,7 @@ INSERT INTO t1 VALUES ('\''); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -2328,7 +2328,7 @@ select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -2483,7 +2483,7 @@ update t1 set a = 4 where a=3; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -2612,7 +2612,7 @@ DELIMITER ; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -2757,7 +2757,7 @@ set sql_mode=''; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -2908,7 +2908,7 @@ set global time_zone='Europe/Moscow'; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -2947,7 +2947,7 @@ UNLOCK TABLES; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; @@ -3081,7 +3081,7 @@ a b c /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -3212,7 +3212,7 @@ SET SQL_MODE = @old_sql_mode; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -3275,7 +3275,7 @@ insert into t1 values ('',''); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -3310,7 +3310,7 @@ UNLOCK TABLES; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -3483,7 +3483,7 @@ insert into t1 values (0815); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -3767,7 +3767,7 @@ CREATE TABLE t1 (a INT) ENGINE=merge UNION=(t2, t3); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -3959,7 +3959,7 @@ create view db42635.v2 (c) as select * from db42635.t1; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -4105,7 +4105,7 @@ INSERT INTO t1 VALUES (3,4), (4,5); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -4368,7 +4368,7 @@ insert into t1 values (0815); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -5634,7 +5634,7 @@ INSERT INTO t1 (a) VALUES (1),(2),(3); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; diff --git a/mysql-test/main/mysqldump.test b/mysql-test/main/mysqldump.test index 61287b3170d..6567596c35c 100644 --- a/mysql-test/main/mysqldump.test +++ b/mysql-test/main/mysqldump.test @@ -1,3 +1,5 @@ +--source include/have_utf8mb4.inc + call mtr.add_suppression("@003f.frm' \\(errno: 22\\)"); #select * from mysql.user; #checksum table mysql.user; diff --git a/mysql-test/main/openssl_1.result b/mysql-test/main/openssl_1.result index ca8d71895e2..3f0483b1e64 100644 --- a/mysql-test/main/openssl_1.result +++ b/mysql-test/main/openssl_1.result @@ -106,7 +106,7 @@ INSERT INTO t1 VALUES (1), (2); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -140,7 +140,7 @@ UNLOCK TABLES; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -174,7 +174,7 @@ UNLOCK TABLES; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; diff --git a/mysql-test/main/openssl_1.test b/mysql-test/main/openssl_1.test index a3db700f787..dce4f88b6bb 100644 --- a/mysql-test/main/openssl_1.test +++ b/mysql-test/main/openssl_1.test @@ -1,3 +1,6 @@ +# Needed for mysqldump +--source include/have_utf8mb4.inc + # Tests for SSL connections, only run if mysqld is compiled # with support for SSL. diff --git a/mysql-test/suite/compat/oracle/r/sp-package-mysqldump.result b/mysql-test/suite/compat/oracle/r/sp-package-mysqldump.result index 1a8e01a992f..21bead42b0a 100644 --- a/mysql-test/suite/compat/oracle/r/sp-package-mysqldump.result +++ b/mysql-test/suite/compat/oracle/r/sp-package-mysqldump.result @@ -38,7 +38,7 @@ $$ /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; +/*!40101 SET NAMES utf8mb4 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; diff --git a/mysql-test/suite/compat/oracle/t/sp-package-mysqldump.test b/mysql-test/suite/compat/oracle/t/sp-package-mysqldump.test index 8f50c1fc4b0..6f3d7964521 100644 --- a/mysql-test/suite/compat/oracle/t/sp-package-mysqldump.test +++ b/mysql-test/suite/compat/oracle/t/sp-package-mysqldump.test @@ -1,3 +1,4 @@ +--source include/have_utf8mb4.inc --source include/not_embedded.inc SET sql_mode=ORACLE; -- cgit v1.2.1 From 00c40efcd69a7d62fb26b66090e47f0f932b0e15 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 12 Oct 2018 16:43:45 +0100 Subject: Fix portability issues with rpl test suite. --- mysql-test/suite/rpl/t/rpl_drop_db.test | 8 ++++---- mysql-test/suite/rpl/t/rpl_mdev382.test | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_drop_db.test b/mysql-test/suite/rpl/t/rpl_drop_db.test index f66187b12f5..372afaa63c6 100644 --- a/mysql-test/suite/rpl/t/rpl_drop_db.test +++ b/mysql-test/suite/rpl/t/rpl_drop_db.test @@ -13,8 +13,8 @@ insert into mysqltest1.t1 values (1); select * from mysqltest1.t1 into outfile 'mysqltest1/f1.txt'; create table mysqltest1.t2 (n int); create table mysqltest1.t3 (n int); ---replace_result \\ / 66 39 93 39 17 39 247 39 "File exists" "Directory not empty" ---error 1010 +--replace_result \\ / 66 39 93 39 17 39 247 39 41 39 "File exists" "Directory not empty" +--error ER_DB_DROP_RMDIR drop database mysqltest1; use mysqltest1; show tables; @@ -30,8 +30,8 @@ while ($1) } --enable_query_log ---replace_result \\ / 66 39 93 39 17 39 247 39 "File exists" "Directory not empty" ---error 1010 +--replace_result \\ / 66 39 93 39 17 39 247 39 41 39 "File exists" "Directory not empty" +--error ER_DB_DROP_RMDIR drop database mysqltest1; use mysqltest1; show tables; diff --git a/mysql-test/suite/rpl/t/rpl_mdev382.test b/mysql-test/suite/rpl/t/rpl_mdev382.test index 3ec877cdb1a..ba1b50648f3 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev382.test +++ b/mysql-test/suite/rpl/t/rpl_mdev382.test @@ -257,7 +257,7 @@ let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); INSERT INTO t1 VALUES(1); --source include/show_binlog_events2.inc let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1); ---exec $MYSQL_BINLOG --short-form --start-position=$binlog_start --stop-position=$pos2 --rewrite-db='test->ts`et' $MYSQLD_DATADIR/master-bin.000002 +--exec $MYSQL_BINLOG --short-form --start-position=$binlog_start --stop-position=$pos2 "--rewrite-db=test->ts`et" $MYSQLD_DATADIR/master-bin.000002 DROP TABLE t1; --source include/rpl_end.inc -- cgit v1.2.1 From 2fd770641ecb476038576cdf3e8829599633292e Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 12 Oct 2018 20:07:08 +0200 Subject: Revert the last change to replication test disable rpl_mdev382 on Windows, due to unix shell escaping used there. --- mysql-test/suite/rpl/t/rpl_mdev382.test | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/t/rpl_mdev382.test b/mysql-test/suite/rpl/t/rpl_mdev382.test index ba1b50648f3..1d951cc7456 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev382.test +++ b/mysql-test/suite/rpl/t/rpl_mdev382.test @@ -1,6 +1,7 @@ --source include/have_innodb.inc --source include/have_binlog_format_statement.inc --source include/master-slave.inc +--source include/not_windows.inc #unix shell escaping used for mysqlbinlog # MDEV-382: multiple SQL injections in replication code. @@ -257,7 +258,7 @@ let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); INSERT INTO t1 VALUES(1); --source include/show_binlog_events2.inc let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1); ---exec $MYSQL_BINLOG --short-form --start-position=$binlog_start --stop-position=$pos2 "--rewrite-db=test->ts`et" $MYSQLD_DATADIR/master-bin.000002 +--exec $MYSQL_BINLOG --short-form --start-position=$binlog_start --stop-position=$pos2 --rewrite-db='test->ts`et' $MYSQLD_DATADIR/master-bin.000002 DROP TABLE t1; --source include/rpl_end.inc -- cgit v1.2.1 From 61bba2a540950335c794c69221e92e136c94d060 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sat, 13 Oct 2018 22:53:12 +0200 Subject: Fix build of embedded server --- sql/rpl_gtid.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 94944b5b3e5..955763fe195 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -329,7 +329,9 @@ rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id, } rgi->gtid_ignore_duplicate_state= rpl_group_info::GTID_DUPLICATE_NULL; +#ifdef HAVE_REPLICATION rgi->pending_gtid_deletes_clear(); +#endif } if (!(list_elem= (list_element *)my_malloc(sizeof(*list_elem), MYF(MY_WME)))) @@ -715,12 +717,16 @@ end: redundant rows in mysql.gtid_slave_pos may accumulate if transactions are rolled back and retried after record_gtid(). */ +#ifdef HAVE_REPLICATION rgi->pending_gtid_deletes_save(gtid->domain_id, elist); +#endif } else { thd->mdl_context.release_transactional_locks(); +#ifdef HAVE_REPLICATION rpl_group_info::pending_gtid_deletes_free(elist); +#endif } } thd->lex->restore_backup_query_tables_list(&lex_backup); -- cgit v1.2.1 From 103b1df510599255f464de5c85a8b0ab1bb1283e Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sun, 14 Oct 2018 15:20:25 -0700 Subject: MDEV-17222 Reproducible server crash in String_list::append_str or in Field_iterator_table::create_item When IN predicate is converted to IN subquery we have to ensure that any item from the select list of the subquery has some name and this name is unique across the select list. This was not guaranteed by the code before the patch for MDEV-17222. If the name of an item of the select list was not set, and this happened for binary constants, then the server crashed. If the first row in the IN list contained the same constant in two different positions then the server returned an error message. This was fixed by providing all constants in the first row of the IN list with generated names. --- mysql-test/main/opt_tvc.result | 67 +++++++++++++++++++++++++++++++----------- mysql-test/main/opt_tvc.test | 40 +++++++++++++++++++++++-- sql/sql_tvc.cc | 19 ++++++++++-- 3 files changed, 105 insertions(+), 21 deletions(-) diff --git a/mysql-test/main/opt_tvc.result b/mysql-test/main/opt_tvc.result index fdbd932a433..d503dab4d99 100644 --- a/mysql-test/main/opt_tvc.result +++ b/mysql-test/main/opt_tvc.result @@ -51,7 +51,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1` +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1` explain extended select * from t1 where a in ( @@ -98,7 +98,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`1` +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`_col_1` explain extended select * from t1 where a in ( @@ -154,7 +154,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join) 4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(4)) `tvc_0` join `test`.`t2`) where `test`.`t2`.`b` = `tvc_0`.`3` +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (3),(4)) `tvc_0` join `test`.`t2`) where `test`.`t2`.`b` = `tvc_0`.`_col_1` explain extended select * from t1 where a in ( @@ -211,7 +211,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 3 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1` +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1` explain extended select * from ( select * @@ -270,7 +270,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 3 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 with tvc_0 as (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` in (1,2))/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1` +Note 1003 with tvc_0 as (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` in (1,2))/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1` explain extended select * from ( select * @@ -321,7 +321,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 3 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1` +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1` explain extended select * from v2; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY ALL distinct_key NULL NULL NULL 2 100.00 @@ -386,7 +386,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 MATERIALIZED t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join) 5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0` join `test`.`t1`) where `test`.`t1`.`a` = 1 and `test`.`t1`.`a` = `tvc_0`.`1` +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0` join `test`.`t1`) where `test`.`t1`.`a` = 1 and `test`.`t1`.`a` = `tvc_0`.`_col_1` explain extended select * from t1 where a in ( @@ -507,11 +507,11 @@ a b explain extended select * from t3 where a in (1,4); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY ALL distinct_key NULL NULL NULL 2 100.00 -1 PRIMARY t3 ref idx idx 5 tvc_0.1 3 100.00 +1 PRIMARY t3 ref idx idx 5 tvc_0._col_1 3 100.00 2 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` semi join ((values (1),(4)) `tvc_0`) where `test`.`t3`.`a` = `tvc_0`.`1` +Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t3` semi join ((values (1),(4)) `tvc_0`) where `test`.`t3`.`a` = `tvc_0`.`_col_1` # use vectors in IN predeicate set @@in_predicate_conversion_threshold= 4; select * from t1 where (a,b) in ((1,2),(3,4)); @@ -524,7 +524,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 MATERIALIZED ALL NULL NULL NULL NULL 2 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1,2),(3,4)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1` and `test`.`t1`.`b` = `tvc_0`.`2` +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1,2),(3,4)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1` and `test`.`t1`.`b` = `tvc_0`.`_col_2` set @@in_predicate_conversion_threshold= 2; # trasformation works for the one IN predicate and doesn't work for the other set @@in_predicate_conversion_threshold= 5; @@ -543,7 +543,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 MATERIALIZED ALL NULL NULL NULL NULL 3 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where `test`.`t2`.`a` = `tvc_0`.`1` and `test`.`t2`.`c` = `tvc_0`.`3` and (`tvc_0`.`1`,`test`.`t2`.`b`) in (((1,2)),((8,9))) +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where `test`.`t2`.`a` = `tvc_0`.`_col_1` and `test`.`t2`.`c` = `tvc_0`.`_col_2` and (`tvc_0`.`_col_1`,`test`.`t2`.`b`) in (((1,2)),((8,9))) set @@in_predicate_conversion_threshold= 2; # # mdev-14281: conversion of NOT IN predicate into subquery predicate @@ -571,7 +571,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 MATERIALIZED ALL NULL NULL NULL NULL 3 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where !<`test`.`t1`.`a`,`test`.`t1`.`b`>(((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( (/* select#2 */ select `tvc_0`.`1`,`tvc_0`.`2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), (`test`.`t1`.`a` in on distinct_key where `test`.`t1`.`a` = ``.`1` and `test`.`t1`.`b` = ``.`2`)))) +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where !<`test`.`t1`.`a`,`test`.`t1`.`b`>(((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( (/* select#2 */ select `tvc_0`.`_col_1`,`tvc_0`.`_col_2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), (`test`.`t1`.`a` in on distinct_key where `test`.`t1`.`a` = ``.`_col_1` and `test`.`t1`.`b` = ``.`_col_2`)))) explain extended select * from t1 where (a,b) not in (select * from (values (1,2),(8,9), (5,1)) as tvc_0); id select_type table type possible_keys key key_len ref rows filtered Extra @@ -593,7 +593,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 MATERIALIZED ALL NULL NULL NULL NULL 3 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`b` < 7 and !<`test`.`t1`.`a`,`test`.`t1`.`b`>(((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( (/* select#2 */ select `tvc_0`.`1`,`tvc_0`.`2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), (`test`.`t1`.`a` in on distinct_key where `test`.`t1`.`a` = ``.`1` and `test`.`t1`.`b` = ``.`2`)))) +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`b` < 7 and !<`test`.`t1`.`a`,`test`.`t1`.`b`>(((`test`.`t1`.`a`,`test`.`t1`.`b`),(`test`.`t1`.`a`,`test`.`t1`.`b`) in ( (/* select#2 */ select `tvc_0`.`_col_1`,`tvc_0`.`_col_2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), (`test`.`t1`.`a` in on distinct_key where `test`.`t1`.`a` = ``.`_col_1` and `test`.`t1`.`b` = ``.`_col_2`)))) select * from t2 where (a,c) not in ((1,2),(8,9), (5,1)); a b c @@ -609,11 +609,11 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 MATERIALIZED ALL NULL NULL NULL NULL 3 100.00 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where !<`test`.`t2`.`a`,`test`.`t2`.`c`>(((`test`.`t2`.`a`,`test`.`t2`.`c`),(`test`.`t2`.`a`,`test`.`t2`.`c`) in ( (/* select#2 */ select `tvc_0`.`1`,`tvc_0`.`2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), (`test`.`t2`.`a` in on distinct_key where `test`.`t2`.`a` = ``.`1` and `test`.`t2`.`c` = ``.`2`)))) +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where !<`test`.`t2`.`a`,`test`.`t2`.`c`>(((`test`.`t2`.`a`,`test`.`t2`.`c`),(`test`.`t2`.`a`,`test`.`t2`.`c`) in ( (/* select#2 */ select `tvc_0`.`_col_1`,`tvc_0`.`_col_2` from (values (1,2),(8,9),(5,1)) `tvc_0` ), (`test`.`t2`.`a` in on distinct_key where `test`.`t2`.`a` = ``.`_col_1` and `test`.`t2`.`c` = ``.`_col_2`)))) drop table t1, t2, t3; set @@in_predicate_conversion_threshold= default; # -# MDEV-14947: conversion of TVC with only NULL values +# MDEV-14947: conversion to TVC with only NULL values # CREATE TABLE t1 (i INT); INSERT INTO t1 VALUES (3), (2), (7); @@ -633,11 +633,11 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY ALL NULL NULL NULL NULL 5 100.00 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`i` AS `i` from `test`.`t1` semi join ((values (NULL),(NULL),(NULL),(NULL),(NULL)) `tvc_0`) where `test`.`t1`.`i` = `tvc_0`.`NULL` +Note 1003 /* select#1 */ select `test`.`t1`.`i` AS `i` from `test`.`t1` semi join ((values (NULL),(NULL),(NULL),(NULL),(NULL)) `tvc_0`) where `test`.`t1`.`i` = `tvc_0`.`_col_1` SET in_predicate_conversion_threshold= default; DROP TABLE t1; # -# MDEV-14835: conversion of TVC with BIGINT or YEAR values +# MDEV-14835: conversion to TVC with BIGINT or YEAR values # SET @@in_predicate_conversion_threshold= 2; CREATE TABLE t1 (a BIGINT); @@ -654,3 +654,36 @@ y 2011 DROP TABLE t1,t2; SET @@in_predicate_conversion_threshold= default; +# +# MDEV-17222: conversion to TVC with no names for constants +# conversion to TVC with the same constants in the first row +# +SET @@in_predicate_conversion_threshold= 2; +CREATE TABLE t1 (f BINARY(16)) ENGINE=MYISAM; +INSERT INTO t1 VALUES +(x'BAE56AF2B1C2397D99D58E2A06761DDB'), (x'9B9B698BCCB939EE8F1EA56C1A2E5DAA'), +(x'A0A1C4FE39A239BABD3E0D8985E6BEA5'); +SELECT COUNT(*) FROM t1 WHERE f IN +(x'9B9B698BCCB939EE8F1EA56C1A2E5DAA', x'E2362DBAB5EA30B5804917A0A7D881E2', +x'B78B2EEAD13635088D93EA3309E24802', x'BAE56AF2B1C2397D99D58E2A06761DDB'); +COUNT(*) +2 +CREATE TABLE t2 (f1 BINARY(16), f2 BINARY(16)) ENGINE=MYISAM; +INSERT INTO t2 VALUES +(x'55FB3B14D6B83D39859E42533906350D', x'00F3458C47FA39DDBEAD918A13F8342E'), +(x'86052C062AAF368D84247ED0F6346A70', x'BF5C35045C6037C79E11026ABB9A3A4E'); +SELECT COUNT(*) FROM t2 WHERE (f1,f2) IN +((x'9B9B698BCCB939EE8F1EA56C1A2E5DAA', x'E2362DBAB5EA30B5804917A0A7D881E2'), +(x'B78B2EEAD13635088D93EA3309E24802', x'BAE56AF2B1C2397D99D58E2A06761DDB'), +(x'55FB3B14D6B83D39859E42533906350D', x'00F3458C47FA39DDBEAD918A13F8342E'), +(x'1606014E7C4A312F83EDC9D91BBFCACA', x'33F6068E56FD3A1D8326517F0D81CB5A')); +COUNT(*) +1 +CREATE TABLE t3 (f1 int, f2 int) ENGINE=MYISAM; +INSERT INTO t3 VALUES (2,5), (2,3), (1,2), (7,8), (1,1); +SELECT * FROM t3 WHERE (f1,f2) IN ((2, 2), (1, 2), (3, 5), (1, 1)); +f1 f2 +1 2 +1 1 +DROP TABLE t1,t2,t3; +SET @@in_predicate_conversion_threshold= default; diff --git a/mysql-test/main/opt_tvc.test b/mysql-test/main/opt_tvc.test index 2d06a0a0b20..733ee0792fe 100644 --- a/mysql-test/main/opt_tvc.test +++ b/mysql-test/main/opt_tvc.test @@ -320,7 +320,7 @@ drop table t1, t2, t3; set @@in_predicate_conversion_threshold= default; --echo # ---echo # MDEV-14947: conversion of TVC with only NULL values +--echo # MDEV-14947: conversion to TVC with only NULL values --echo # CREATE TABLE t1 (i INT); @@ -342,7 +342,7 @@ SET in_predicate_conversion_threshold= default; DROP TABLE t1; --echo # ---echo # MDEV-14835: conversion of TVC with BIGINT or YEAR values +--echo # MDEV-14835: conversion to TVC with BIGINT or YEAR values --echo # SET @@in_predicate_conversion_threshold= 2; @@ -360,3 +360,39 @@ SELECT * FROM t2 WHERE y IN ('2009','2011'); DROP TABLE t1,t2; SET @@in_predicate_conversion_threshold= default; + +--echo # +--echo # MDEV-17222: conversion to TVC with no names for constants +--echo # conversion to TVC with the same constants in the first row +--echo # + +SET @@in_predicate_conversion_threshold= 2; + +CREATE TABLE t1 (f BINARY(16)) ENGINE=MYISAM; +INSERT INTO t1 VALUES +(x'BAE56AF2B1C2397D99D58E2A06761DDB'), (x'9B9B698BCCB939EE8F1EA56C1A2E5DAA'), +(x'A0A1C4FE39A239BABD3E0D8985E6BEA5'); + +SELECT COUNT(*) FROM t1 WHERE f IN +(x'9B9B698BCCB939EE8F1EA56C1A2E5DAA', x'E2362DBAB5EA30B5804917A0A7D881E2', + x'B78B2EEAD13635088D93EA3309E24802', x'BAE56AF2B1C2397D99D58E2A06761DDB'); + +CREATE TABLE t2 (f1 BINARY(16), f2 BINARY(16)) ENGINE=MYISAM; +INSERT INTO t2 VALUES +(x'55FB3B14D6B83D39859E42533906350D', x'00F3458C47FA39DDBEAD918A13F8342E'), +(x'86052C062AAF368D84247ED0F6346A70', x'BF5C35045C6037C79E11026ABB9A3A4E'); + +SELECT COUNT(*) FROM t2 WHERE (f1,f2) IN +((x'9B9B698BCCB939EE8F1EA56C1A2E5DAA', x'E2362DBAB5EA30B5804917A0A7D881E2'), + (x'B78B2EEAD13635088D93EA3309E24802', x'BAE56AF2B1C2397D99D58E2A06761DDB'), + (x'55FB3B14D6B83D39859E42533906350D', x'00F3458C47FA39DDBEAD918A13F8342E'), + (x'1606014E7C4A312F83EDC9D91BBFCACA', x'33F6068E56FD3A1D8326517F0D81CB5A')); + +CREATE TABLE t3 (f1 int, f2 int) ENGINE=MYISAM; +INSERT INTO t3 VALUES (2,5), (2,3), (1,2), (7,8), (1,1); + +SELECT * FROM t3 WHERE (f1,f2) IN ((2, 2), (1, 2), (3, 5), (1, 1)); + +DROP TABLE t1,t2,t3; + +SET @@in_predicate_conversion_threshold= default; diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index 188ba8c4629..a5085fdfc58 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -470,6 +470,7 @@ bool Item_func_in::create_value_list_for_tvc(THD *thd, for (uint i=1; i < arg_count; i++) { + char col_name[8]; List *tvc_value; if (!(tvc_value= new (thd->mem_root) List())) return true; @@ -480,13 +481,27 @@ bool Item_func_in::create_value_list_for_tvc(THD *thd, for (uint j=0; j < row_list->cols(); j++) { + if (i == 1) + { + sprintf(col_name, "_col_%i", j+1); + row_list->element_index(j)->set_name(thd, col_name, strlen(col_name), + thd->charset()); + } if (tvc_value->push_back(row_list->element_index(j), thd->mem_root)) return true; } } - else if (tvc_value->push_back(args[i]->real_item())) - return true; + else + { + if (i == 1) + { + sprintf(col_name, "_col_%i", 1); + args[i]->set_name(thd, col_name, strlen(col_name), thd->charset()); + } + if (tvc_value->push_back(args[i]->real_item())) + return true; + } if (values->push_back(tvc_value, thd->mem_root)) return true; -- cgit v1.2.1 From 97a37edc970f8619ffd23394b61fe310d705d0ef Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Mon, 15 Oct 2018 09:35:19 -0700 Subject: MDEV-17137: Syntax errors with VIEW using MEDIAN The syntax error happened because we had not implemented a different print for percentile functions. The syntax is a bit different when we use percentile functions as window functions in comparision to normal window functions. Implemented a seperate print function for percentile functions --- mysql-test/main/win_percentile.result | 18 ++++++++++++++++++ mysql-test/main/win_percentile.test | 12 ++++++++++++ sql/item_windowfunc.cc | 17 +++++++++++++++++ sql/item_windowfunc.h | 1 + sql/sql_window.cc | 19 ++++++++++++++++--- sql/sql_window.h | 2 ++ 6 files changed, 66 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/win_percentile.result b/mysql-test/main/win_percentile.result index f46fad80d16..6ae18488697 100644 --- a/mysql-test/main/win_percentile.result +++ b/mysql-test/main/win_percentile.result @@ -348,3 +348,21 @@ MEDIAN(`a2`) OVER (PARTITION BY `pk`) FROM t1; MEDIAN(`a1`) OVER () MEDIAN(`a2`) OVER (PARTITION BY `pk`) DROP TABLE t1; +# +# MDEV-17137: Syntax errors with VIEW using MEDIAN +# +CREATE TABLE t1(val int); +INSERT INTO t1 VALUES (1), (2), (3); +CREATE VIEW v1 AS SELECT MEDIAN(val) OVER() FROM t1; +select * from v1; +MEDIAN(val) OVER() +2.0000000000 +2.0000000000 +2.0000000000 +select median(val) OVER () FROM t1; +median(val) OVER () +2.0000000000 +2.0000000000 +2.0000000000 +drop table t1; +drop view v1; diff --git a/mysql-test/main/win_percentile.test b/mysql-test/main/win_percentile.test index e39af8cfd39..a709b38d2e6 100644 --- a/mysql-test/main/win_percentile.test +++ b/mysql-test/main/win_percentile.test @@ -127,3 +127,15 @@ SELECT MEDIAN(`a1`) OVER (), MEDIAN(`a2`) OVER (PARTITION BY `pk`) FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-17137: Syntax errors with VIEW using MEDIAN +--echo # + +CREATE TABLE t1(val int); +INSERT INTO t1 VALUES (1), (2), (3); +CREATE VIEW v1 AS SELECT MEDIAN(val) OVER() FROM t1; +select * from v1; +select median(val) OVER () FROM t1; +drop table t1; +drop view v1; diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc index 3ad0527384d..2db396d3065 100644 --- a/sql/item_windowfunc.cc +++ b/sql/item_windowfunc.cc @@ -545,6 +545,11 @@ void Item_sum_hybrid_simple::update_field() void Item_window_func::print(String *str, enum_query_type query_type) { + if (only_single_element_order_list()) + { + print_for_percentile_functions(str, query_type); + return; + } window_func()->print(str, query_type); str->append(" over "); #ifndef DBUG_OFF @@ -554,3 +559,15 @@ void Item_window_func::print(String *str, enum_query_type query_type) #endif window_spec->print(str, query_type); } +void Item_window_func::print_for_percentile_functions(String *str, enum_query_type query_type) +{ + window_func()->print(str, query_type); + str->append(" within group "); + str->append('('); + window_spec->print_order(str,query_type); + str->append(')'); + str->append(" over "); + str->append('('); + window_spec->print_partition(str,query_type); + str->append(')'); +} diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h index b3e23748246..9ba60c3956d 100644 --- a/sql/item_windowfunc.h +++ b/sql/item_windowfunc.h @@ -1155,6 +1155,7 @@ private: */ bool force_return_blank; bool read_value_from_result_field; + void print_for_percentile_functions(String *str, enum_query_type query_type); public: void set_phase_to_initial() diff --git a/sql/sql_window.cc b/sql/sql_window.cc index 38fdd8ab80b..e4d69f2fa5e 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -82,19 +82,32 @@ void Window_spec::print(String *str, enum_query_type query_type) { str->append('('); + print_partition(str, query_type); + print_order(str, query_type); + + if (window_frame) + window_frame->print(str, query_type); + str->append(')'); +} + +void +Window_spec::print_partition(String *str, enum_query_type query_type) +{ if (partition_list->first) { str->append(STRING_WITH_LEN(" partition by ")); st_select_lex::print_order(str, partition_list->first, query_type); } +} + +void +Window_spec::print_order(String *str, enum_query_type query_type) +{ if (order_list->first) { str->append(STRING_WITH_LEN(" order by ")); st_select_lex::print_order(str, order_list->first, query_type); } - if (window_frame) - window_frame->print(str, query_type); - str->append(')'); } bool diff --git a/sql/sql_window.h b/sql/sql_window.h index 392f89e8f03..bf59f00d764 100644 --- a/sql/sql_window.h +++ b/sql/sql_window.h @@ -147,6 +147,8 @@ class Window_spec : public Sql_alloc } void print(String *str, enum_query_type query_type); + void print_order(String *str, enum_query_type query_type); + void print_partition(String *str, enum_query_type query_type); }; -- cgit v1.2.1 From c2c1550f57bf61e60b778dc889be132cca176ff3 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 17 Oct 2018 04:37:25 -0700 Subject: MDEV-17419 Subquery with group by returns wrong results Added only test case because the bug was fixed by the patch for mdev-17382. --- mysql-test/main/derived_cond_pushdown.result | 40 +++++++++++++++++++++++++++ mysql-test/main/derived_cond_pushdown.test | 41 ++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 51a4703d5d4..b6ebc4ee855 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -16448,3 +16448,43 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1003 /* select#1 */ select `test`.`t3`.`d` AS `d`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from `test`.`t3` join (/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`b` = `test`.`t3`.`d` group by `test`.`t1`.`b`,`test`.`t2`.`c`) `dt` where `dt`.`b` = `test`.`t3`.`d` DROP TABLE t1,t2,t3; +# +# MDEV-17419: splittable materialized derived/view +# when join_cache_level = 4 +# +set join_cache_level = 4; +CREATE TABLE t1 ( +id INT UNSIGNED NOT NULL AUTO_INCREMENT, +username VARCHAR(50) NULL DEFAULT '0', +PRIMARY KEY (id) +) COLLATE='utf8_general_ci'; +CREATE TABLE t2 ( +id INT UNSIGNED NOT NULL AUTO_INCREMENT, +userid INT UNSIGNED NOT NULL, +logindate DATETIME NOT NULL, +PRIMARY KEY (id) +) COLLATE='utf8_general_ci'; +INSERT INTO t1 (id, username) VALUES +(1,"user1"), (2, "user2"); +INSERT INTO t2 (id, userid, logindate) VALUES +(1,1,"2015-06-19 12:17:02.828"), +(2,1,"2016-06-19 12:17:02.828"), +(3,2,"2017-06-19 12:17:02.828"), +(4,2,"2018-06-19 12:17:02.828"); +EXPLAIN select * from t1 as u +left join +(select * from t2 as au group by au.userid) as auditlastlogin +on u.id=auditlastlogin.userid; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY u ALL NULL NULL NULL NULL 2 +1 PRIMARY ref key0 key0 5 test.u.id 2 +2 DERIVED au ALL NULL NULL NULL NULL 4 Using temporary; Using filesort +select * from t1 as u +left join +(select * from t2 as au group by au.userid) as auditlastlogin +on u.id=auditlastlogin.userid; +id username id userid logindate +1 user1 1 1 2015-06-19 12:17:02 +2 user2 3 2 2017-06-19 12:17:02 +set join_cache_level=default; +DROP TABLE t1,t2; diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index 61541d2cdf5..1de1e8a8d15 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -3143,3 +3143,44 @@ eval $q; eval EXPLAIN EXTENDED $q; DROP TABLE t1,t2,t3; + +--echo # +--echo # MDEV-17419: splittable materialized derived/view +--echo # when join_cache_level = 4 +--echo # + +set join_cache_level = 4; + +CREATE TABLE t1 ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + username VARCHAR(50) NULL DEFAULT '0', + PRIMARY KEY (id) +) COLLATE='utf8_general_ci'; + +CREATE TABLE t2 ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + userid INT UNSIGNED NOT NULL, + logindate DATETIME NOT NULL, + PRIMARY KEY (id) +) COLLATE='utf8_general_ci'; + +INSERT INTO t1 (id, username) VALUES + (1,"user1"), (2, "user2"); +INSERT INTO t2 (id, userid, logindate) VALUES + (1,1,"2015-06-19 12:17:02.828"), + (2,1,"2016-06-19 12:17:02.828"), + (3,2,"2017-06-19 12:17:02.828"), + (4,2,"2018-06-19 12:17:02.828"); + +let $q= +select * from t1 as u + left join + (select * from t2 as au group by au.userid) as auditlastlogin + on u.id=auditlastlogin.userid; + +eval EXPLAIN $q; +eval $q; + +set join_cache_level=default; + +DROP TABLE t1,t2; -- cgit v1.2.1 From 2fa4ed031ce6cc6370671058ccc3d119b8cb3d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 17 Oct 2018 18:55:46 +0300 Subject: MDEV-17483 Insert on delete-marked record can wrongly inherit old values for instantly added column row_ins_clust_index_entry_low(): Do not call dtuple_t::trim() before row_ins_clust_index_entry_by_modify(), so that the values of all columns will be available in row_upd_build_difference_binary(). If applicable, the tuple can be trimmed in btr_cur_optimistic_update() or btr_cur_pessimistic_update(), which will be called by row_ins_clust_index_entry_by_modify(). --- mysql-test/suite/innodb/r/instant_alter.result | 47 +++++++++++++++++++++++++- mysql-test/suite/innodb/t/instant_alter.test | 18 ++++++++++ storage/innobase/row/row0ins.cc | 3 +- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/innodb/r/instant_alter.result b/mysql-test/suite/innodb/r/instant_alter.result index 2f56d0eca4f..3ebc161caf1 100644 --- a/mysql-test/suite/innodb/r/instant_alter.result +++ b/mysql-test/suite/innodb/r/instant_alter.result @@ -471,6 +471,21 @@ Table Op Msg_type Msg_text test.t2 check status OK test.t1 check status OK DROP TABLE t2, t1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1 SET a = 1; +ALTER TABLE t1 ADD COLUMN b TEXT; +BEGIN; +UPDATE t1 SET b = REPEAT('1', 32768); +UPDATE t1 SET a = 2; +INSERT INTO t1 SET a = 1; +SELECT a,LENGTH(b) FROM t1; +a LENGTH(b) +1 NULL +2 32768 +DELETE FROM t1; +COMMIT; +InnoDB 0 transactions not purged +DROP TABLE t1; CREATE TABLE t1 (id INT PRIMARY KEY, c2 INT UNIQUE, c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'), @@ -888,6 +903,21 @@ Table Op Msg_type Msg_text test.t2 check status OK test.t1 check status OK DROP TABLE t2, t1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 SET a = 1; +ALTER TABLE t1 ADD COLUMN b TEXT; +BEGIN; +UPDATE t1 SET b = REPEAT('1', 32768); +UPDATE t1 SET a = 2; +INSERT INTO t1 SET a = 1; +SELECT a,LENGTH(b) FROM t1; +a LENGTH(b) +1 NULL +2 32768 +DELETE FROM t1; +COMMIT; +InnoDB 0 transactions not purged +DROP TABLE t1; CREATE TABLE t1 (id INT PRIMARY KEY, c2 INT UNIQUE, c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'), @@ -1305,10 +1335,25 @@ Table Op Msg_type Msg_text test.t2 check status OK test.t1 check status OK DROP TABLE t2, t1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 SET a = 1; +ALTER TABLE t1 ADD COLUMN b TEXT; +BEGIN; +UPDATE t1 SET b = REPEAT('1', 32768); +UPDATE t1 SET a = 2; +INSERT INTO t1 SET a = 1; +SELECT a,LENGTH(b) FROM t1; +a LENGTH(b) +1 NULL +2 32768 +DELETE FROM t1; +COMMIT; +InnoDB 0 transactions not purged +DROP TABLE t1; disconnect analyze; SELECT variable_value-@old_instant instants FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -48 +51 SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; diff --git a/mysql-test/suite/innodb/t/instant_alter.test b/mysql-test/suite/innodb/t/instant_alter.test index 720e495e3a7..3e62038e591 100644 --- a/mysql-test/suite/innodb/t/instant_alter.test +++ b/mysql-test/suite/innodb/t/instant_alter.test @@ -343,6 +343,24 @@ DEFAULT REPEAT('a', @@GLOBAL.innodb_page_size * .75); CHECK TABLE t2, t1; DROP TABLE t2, t1; +# +# MDEV-17483 Insert on delete-marked record can wrongly inherit old values +# for instantly added column +# + +eval CREATE TABLE t1 (a INT PRIMARY KEY) $engine; +INSERT INTO t1 SET a = 1; +ALTER TABLE t1 ADD COLUMN b TEXT; +BEGIN; +UPDATE t1 SET b = REPEAT('1', 32768); +UPDATE t1 SET a = 2; +INSERT INTO t1 SET a = 1; +SELECT a,LENGTH(b) FROM t1; +DELETE FROM t1; +COMMIT; +--source include/wait_all_purged.inc +DROP TABLE t1; + dec $format; } disconnect analyze; diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index ea5bc2a4f50..4620e493982 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2671,8 +2671,6 @@ row_ins_clust_index_entry_low( } } - if (index->is_instant()) entry->trim(*index); - if (rec_is_metadata(btr_cur_get_rec(cursor), index)) { goto do_insert; } @@ -2739,6 +2737,7 @@ err_exit: mtr_commit(&mtr); mem_heap_free(entry_heap); } else { + if (index->is_instant()) entry->trim(*index); do_insert: rec_t* insert_rec; -- cgit v1.2.1