From 848e08acf6cf311fd222c3465e8e312e0cdba050 Mon Sep 17 00:00:00 2001 From: Thomas Young Date: Thu, 4 Jun 2015 09:19:41 +0200 Subject: [PATCH] Regression tests and fix for issue 116 (Unnecessary certification failures on TOI DDLs) It looks like the provider api doesn't permit TOI replication *without any keys*, which is what we would ideally do here, so we instead just supply a table key that should not match any existing table. The regression tests and fix target 3 specific table creation code paths (and do not address alter statements or other potential related issues): 1. Basic CREATE TABLE statements 2. CREATE TABLE LIKE, where the source table is a temporary table 3. CREATE TABLE LIKE, where the source table is not a temporary table --- .../r/galera_create_table_deadlock.result | 17 +++++++ .../galera_create_table_like_deadlock.result | 19 ++++++++ ...reate_table_like_temporary_deadlock.result | 18 +++++++ .../t/galera_create_table_deadlock.test | 45 ++++++++++++++++++ .../t/galera_create_table_like_deadlock.test | 47 +++++++++++++++++++ ..._create_table_like_temporary_deadlock.test | 46 ++++++++++++++++++ sql/sql_parse.cc | 3 +- sql/sql_parse.h | 8 ++++ sql/sql_table.cc | 6 +-- 9 files changed, 204 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_create_table_deadlock.result create mode 100644 mysql-test/suite/galera/r/galera_create_table_like_deadlock.result create mode 100644 mysql-test/suite/galera/r/galera_create_table_like_temporary_deadlock.result create mode 100644 mysql-test/suite/galera/t/galera_create_table_deadlock.test create mode 100644 mysql-test/suite/galera/t/galera_create_table_like_deadlock.test create mode 100644 mysql-test/suite/galera/t/galera_create_table_like_temporary_deadlock.test diff --git a/mysql-test/suite/galera/r/galera_create_table_deadlock.result b/mysql-test/suite/galera/r/galera_create_table_deadlock.result new file mode 100644 index 00000000000..4f814056649 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_create_table_deadlock.result @@ -0,0 +1,17 @@ +SET GLOBAL wsrep_debug=ON; +SET GLOBAL wsrep_sync_wait=0; +SET GLOBAL wsrep_retry_autocommit=0; +SET SESSION wsrep_sync_wait=0; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET GLOBAL wsrep_provider_options = 'debug=1;dbug=d,local_monitor_enter_sync'; +CREATE TABLE IF NOT EXISTS t1 (f1 INTEGER) ENGINE=InnoDB;; +INSERT INTO t1 VALUES (1);; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SHOW STATUS LIKE 'wsrep_local_cert_failures'; +Variable_name Value +wsrep_local_cert_failures 0 +SET GLOBAL wsrep_retry_autocommit=1; +SET GLOBAL wsrep_sync_wait=7; +SET GLOBAL wsrep_debug=OFF; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_create_table_like_deadlock.result b/mysql-test/suite/galera/r/galera_create_table_like_deadlock.result new file mode 100644 index 00000000000..331fe3e06a7 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_create_table_like_deadlock.result @@ -0,0 +1,19 @@ +SET GLOBAL wsrep_debug=ON; +SET GLOBAL wsrep_sync_wait=0; +SET GLOBAL wsrep_retry_autocommit=0; +SET SESSION wsrep_sync_wait=0; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET GLOBAL wsrep_provider_options = 'debug=1;dbug=d,local_monitor_enter_sync'; +CREATE TABLE IF NOT EXISTS t1 LIKE t2;; +INSERT INTO t1 VALUES (1);; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SHOW STATUS LIKE 'wsrep_local_cert_failures'; +Variable_name Value +wsrep_local_cert_failures 0 +SET GLOBAL wsrep_retry_autocommit=1; +SET GLOBAL wsrep_sync_wait=7; +SET GLOBAL wsrep_debug=OFF; +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_create_table_like_temporary_deadlock.result b/mysql-test/suite/galera/r/galera_create_table_like_temporary_deadlock.result new file mode 100644 index 00000000000..e84cd187d38 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_create_table_like_temporary_deadlock.result @@ -0,0 +1,18 @@ +SET GLOBAL wsrep_debug=ON; +SET GLOBAL wsrep_sync_wait=0; +SET GLOBAL wsrep_retry_autocommit=0; +SET SESSION wsrep_sync_wait=0; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET GLOBAL wsrep_provider_options = 'debug=1;dbug=d,local_monitor_enter_sync'; +CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE IF NOT EXISTS t1 LIKE t2;; +INSERT INTO t1 VALUES (1);; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SHOW STATUS LIKE 'wsrep_local_cert_failures'; +Variable_name Value +wsrep_local_cert_failures 0 +SET GLOBAL wsrep_retry_autocommit=1; +SET GLOBAL wsrep_sync_wait=7; +SET GLOBAL wsrep_debug=OFF; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_create_table_deadlock.test b/mysql-test/suite/galera/t/galera_create_table_deadlock.test new file mode 100644 index 00000000000..8fc9d49a4e7 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_create_table_deadlock.test @@ -0,0 +1,45 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source suite/galera/include/galera_have_debug_sync.inc + +SET GLOBAL wsrep_debug=ON; +SET GLOBAL wsrep_sync_wait=0; +SET GLOBAL wsrep_retry_autocommit=0; + +--connection node_1 +SET SESSION wsrep_sync_wait=0; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET GLOBAL wsrep_provider_options = 'debug=1;dbug=d,local_monitor_enter_sync'; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +--send CREATE TABLE IF NOT EXISTS t1 (f1 INTEGER) ENGINE=InnoDB; + +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1b + +--let $wait_condition = SELECT VARIABLE_VALUE = 'local_monitor_enter_sync' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' +--source include/wait_condition.inc + +--send INSERT INTO t1 VALUES (1); + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 'local_monitor_enter_sync local_monitor_enter_sync' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' +--source include/wait_condition.inc + + +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; + +--connection node_1b +# (was causing a deadlock due to create table statement adding table key to write set) +#--error ER_LOCK_DEADLOCK +--reap + +--connection node_1 +SHOW STATUS LIKE 'wsrep_local_cert_failures'; +SET GLOBAL wsrep_retry_autocommit=1; +SET GLOBAL wsrep_sync_wait=7; +SET GLOBAL wsrep_debug=OFF; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_create_table_like_deadlock.test b/mysql-test/suite/galera/t/galera_create_table_like_deadlock.test new file mode 100644 index 00000000000..19b0624f38d --- /dev/null +++ b/mysql-test/suite/galera/t/galera_create_table_like_deadlock.test @@ -0,0 +1,47 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source suite/galera/include/galera_have_debug_sync.inc + +SET GLOBAL wsrep_debug=ON; +SET GLOBAL wsrep_sync_wait=0; +SET GLOBAL wsrep_retry_autocommit=0; + +--connection node_1 +SET SESSION wsrep_sync_wait=0; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET GLOBAL wsrep_provider_options = 'debug=1;dbug=d,local_monitor_enter_sync'; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +--send CREATE TABLE IF NOT EXISTS t1 LIKE t2; + +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1b + +--let $wait_condition = SELECT VARIABLE_VALUE = 'local_monitor_enter_sync' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' +--source include/wait_condition.inc + +--send INSERT INTO t1 VALUES (1); + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 'local_monitor_enter_sync local_monitor_enter_sync' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' +--source include/wait_condition.inc + + +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; + +--connection node_1b +# (was causing a deadlock due to create table statement adding table key to write set) +#--error ER_LOCK_DEADLOCK +--reap + +--connection node_1 +SHOW STATUS LIKE 'wsrep_local_cert_failures'; +SET GLOBAL wsrep_retry_autocommit=1; +SET GLOBAL wsrep_sync_wait=7; +SET GLOBAL wsrep_debug=OFF; +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/t/galera_create_table_like_temporary_deadlock.test b/mysql-test/suite/galera/t/galera_create_table_like_temporary_deadlock.test new file mode 100644 index 00000000000..489b6f6c2be --- /dev/null +++ b/mysql-test/suite/galera/t/galera_create_table_like_temporary_deadlock.test @@ -0,0 +1,46 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source suite/galera/include/galera_have_debug_sync.inc + +SET GLOBAL wsrep_debug=ON; +SET GLOBAL wsrep_sync_wait=0; +SET GLOBAL wsrep_retry_autocommit=0; + +--connection node_1 +SET SESSION wsrep_sync_wait=0; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET GLOBAL wsrep_provider_options = 'debug=1;dbug=d,local_monitor_enter_sync'; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +--send CREATE TABLE IF NOT EXISTS t1 LIKE t2; + +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1b + +--let $wait_condition = SELECT VARIABLE_VALUE = 'local_monitor_enter_sync' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' +--source include/wait_condition.inc + +--send INSERT INTO t1 VALUES (1); + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 'local_monitor_enter_sync local_monitor_enter_sync' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' +--source include/wait_condition.inc + + +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; + +--connection node_1b +# (was causing a deadlock due to create table statement adding table key to write set) +#--error ER_LOCK_DEADLOCK +--reap + +--connection node_1 +SHOW STATUS LIKE 'wsrep_local_cert_failures'; +SET GLOBAL wsrep_retry_autocommit=1; +SET GLOBAL wsrep_sync_wait=7; +SET GLOBAL wsrep_debug=OFF; +DROP TABLE t1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e94c1a2ba4c..bc988469dae 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3369,8 +3369,7 @@ case SQLCOM_PREPARE: */ if (!thd->is_current_stmt_binlog_format_row() || !(create_info.options & HA_LEX_CREATE_TMP_TABLE)) - WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, - NULL) + WSREP_TO_ISOLATION_BEGIN(create_table->db, WSREP_NONEXISTANT_TABLE, NULL) #endif /* WITH_WSREP */ /* Regular CREATE TABLE */ res= mysql_create_table(thd, create_table, diff --git a/sql/sql_parse.h b/sql/sql_parse.h index c54bc964925..b90760ab831 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -212,6 +212,14 @@ inline bool is_supported_parser_charset(const CHARSET_INFO *cs) } #ifdef WITH_WSREP +/* + This is used in cases where at least one key is required by the API + but we don't actually want to add any key to the write set. + (A space is added to the end, with the intention that no one should + ever be able to create a real table with this name.) +*/ +#define WSREP_NONEXISTANT_TABLE (char *)"nonexistant table " + #define WSREP_MYSQL_DB (char *)"mysql" #define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 41e0af470df..d31859ab501 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5334,8 +5334,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, } else if (!is_tmp_table) { - /* this is straight CREATE TABLE LIKE... eith no tmp tables */ - WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL); + /* this is straight CREATE TABLE LIKE... with no tmp tables */ + WSREP_TO_ISOLATION_BEGIN(table->db, WSREP_NONEXISTANT_TABLE, NULL); } else { @@ -5358,7 +5358,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, thd->wsrep_TOI_pre_query= query.ptr(); thd->wsrep_TOI_pre_query_len= query.length(); - WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL); + WSREP_TO_ISOLATION_BEGIN(table->db, WSREP_NONEXISTANT_TABLE, NULL); thd->wsrep_TOI_pre_query= NULL; thd->wsrep_TOI_pre_query_len= 0;