From af2f7ce3f915c4686ef04294b00c6f4885503f5e Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sun, 19 Jul 2015 22:51:19 -0400 Subject: [PATCH 01/14] MDEV-8464 : ALTER VIEW not replicated in some cases In galera, like other DDLs, CREATE/ALTER VIEW commands are recreated and replicated during parsing. The ALGORITHM clause is internally set to VIEW_ALGORITHM_INHERIT if its not explicitly specified by the user. But since its not a valid type to be used in a command, it leads to an assertion failure. The solution is to not include the ALGORITHM clause in the command if its not explicitly specified (or INHERIT). --- mysql-test/suite/galera/r/view.result | 46 ++++++++++++++++++++ mysql-test/suite/galera/t/view.test | 43 +++++++++++++++++++ sql/sql_show.cc | 60 +++++++++++++++++---------- sql/sql_show.h | 2 + sql/wsrep_mysqld.cc | 2 +- 5 files changed, 129 insertions(+), 24 deletions(-) create mode 100644 mysql-test/suite/galera/r/view.result create mode 100644 mysql-test/suite/galera/t/view.test diff --git a/mysql-test/suite/galera/r/view.result b/mysql-test/suite/galera/r/view.result new file mode 100644 index 00000000000..4ab34e4a26a --- /dev/null +++ b/mysql-test/suite/galera/r/view.result @@ -0,0 +1,46 @@ +# +# MDEV-8464 : ALTER VIEW not replicated in some cases +# +# On node_1 +USE test; +CREATE TABLE t1(i INT) ENGINE=INNODB; +CREATE DEFINER=CURRENT_USER VIEW v1 AS SELECT * FROM t1; +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t1; +CREATE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t1; +CREATE ALGORITHM=UNDEFINED DEFINER=CURRENT_USER VIEW v4 AS SELECT * FROM t1; +# On node_2 +USE test; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci +SHOW CREATE VIEW v2; +View Create View character_set_client collation_connection +v2 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci +SHOW CREATE VIEW v3; +View Create View character_set_client collation_connection +v3 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci +SHOW CREATE VIEW v4; +View Create View character_set_client collation_connection +v4 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v4` AS select `t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci +# On node_1 +ALTER ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; +ALTER ALGORITHM=UNDEFINED VIEW v2 AS SELECT * FROM t1; +ALTER DEFINER=CURRENT_USER VIEW v3 AS SELECT * FROM t1; +ALTER ALGORITHM=TEMPTABLE DEFINER=CURRENT_USER VIEW v4 AS SELECT * FROM t1; +# On node_2 +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci +SHOW CREATE VIEW v2; +View Create View character_set_client collation_connection +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci +SHOW CREATE VIEW v3; +View Create View character_set_client collation_connection +v3 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci +SHOW CREATE VIEW v4; +View Create View character_set_client collation_connection +v4 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v4` AS select `t1`.`i` AS `i` from `t1` latin1 latin1_swedish_ci +# Cleanup +DROP VIEW v1, v2, v3, v4; +DROP TABLE t1; +# End of tests diff --git a/mysql-test/suite/galera/t/view.test b/mysql-test/suite/galera/t/view.test new file mode 100644 index 00000000000..d72ad264358 --- /dev/null +++ b/mysql-test/suite/galera/t/view.test @@ -0,0 +1,43 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--echo # +--echo # MDEV-8464 : ALTER VIEW not replicated in some cases +--echo # +--echo # On node_1 +--connection node_1 +USE test; +CREATE TABLE t1(i INT) ENGINE=INNODB; +CREATE DEFINER=CURRENT_USER VIEW v1 AS SELECT * FROM t1; +CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM t1; +CREATE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t1; +CREATE ALGORITHM=UNDEFINED DEFINER=CURRENT_USER VIEW v4 AS SELECT * FROM t1; + +--echo # On node_2 +--connection node_2 +USE test; +SHOW CREATE VIEW v1; +SHOW CREATE VIEW v2; +SHOW CREATE VIEW v3; +SHOW CREATE VIEW v4; + +--echo # On node_1 +--connection node_1 +ALTER ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; +ALTER ALGORITHM=UNDEFINED VIEW v2 AS SELECT * FROM t1; +ALTER DEFINER=CURRENT_USER VIEW v3 AS SELECT * FROM t1; +ALTER ALGORITHM=TEMPTABLE DEFINER=CURRENT_USER VIEW v4 AS SELECT * FROM t1; + +--echo # On node_2 +--connection node_2 +SHOW CREATE VIEW v1; +SHOW CREATE VIEW v2; +SHOW CREATE VIEW v3; +SHOW CREATE VIEW v4; + +--echo # Cleanup +DROP VIEW v1, v2, v3, v4; +DROP TABLE t1; + +--echo # End of tests + diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1ff842d9723..e7a82927a40 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -119,9 +119,6 @@ static void get_cs_converted_string_value(THD *thd, bool use_hex); #endif -static void -append_algorithm(TABLE_LIST *table, String *buff); - static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table); /*************************************************************************** @@ -1972,32 +1969,30 @@ static void store_key_options(THD *thd, String *packet, TABLE *table, } } - -void -view_store_options(THD *thd, TABLE_LIST *table, String *buff) -{ - append_algorithm(table, buff); - append_definer(thd, buff, &table->definer.user, &table->definer.host); - if (table->view_suid) - buff->append(STRING_WITH_LEN("SQL SECURITY DEFINER ")); - else - buff->append(STRING_WITH_LEN("SQL SECURITY INVOKER ")); -} - - /* - Append DEFINER clause to the given buffer. + Append ALGORITHM clause to the given buffer. SYNOPSIS - append_definer() - thd [in] thread handle - buffer [inout] buffer to hold DEFINER clause - definer_user [in] user name part of definer - definer_host [in] host name part of definer + append_algorithm() + table [in] table list + buff [inout] buffer to hold the ALGORITHM clause + check_inherit [in] if true, do nothing if algorithm is INHERIT */ -static void append_algorithm(TABLE_LIST *table, String *buff) +static void append_algorithm(TABLE_LIST *table, String *buff, + bool check_inherit) { + int16 algorithm= (int16) table->algorithm; + + DBUG_ENTER("append_algorithm"); + + /* + Handle a special case when ALGORITHM is not specified, in which case we + simply return. + */ + if (check_inherit && (algorithm == VIEW_ALGORITHM_INHERIT)) + DBUG_VOID_RETURN; + buff->append(STRING_WITH_LEN("ALGORITHM=")); switch ((int16)table->algorithm) { case VIEW_ALGORITHM_UNDEFINED: @@ -2012,6 +2007,8 @@ static void append_algorithm(TABLE_LIST *table, String *buff) default: DBUG_ASSERT(0); // never should happen } + + DBUG_VOID_RETURN; } /* @@ -2035,6 +2032,23 @@ void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user, buffer->append(' '); } +void +view_store_options4(THD *thd, TABLE_LIST *table, String *buff, + bool check_inherit) +{ + append_algorithm(table, buff, check_inherit); + append_definer(thd, buff, &table->definer.user, &table->definer.host); + if (table->view_suid) + buff->append(STRING_WITH_LEN("SQL SECURITY DEFINER ")); + else + buff->append(STRING_WITH_LEN("SQL SECURITY INVOKER ")); +} + +void +view_store_options(THD *thd, TABLE_LIST *table, String *buff) +{ + view_store_options4(thd, table, buff, false); +} int view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) diff --git a/sql/sql_show.h b/sql/sql_show.h index 6e87f6097f0..04997fe8965 100644 --- a/sql/sql_show.h +++ b/sql/sql_show.h @@ -115,6 +115,8 @@ void free_status_vars(); void reset_status_vars(); bool show_create_trigger(THD *thd, const sp_name *trg_name); void view_store_options(THD *thd, TABLE_LIST *table, String *buff); +void view_store_options4(THD *thd, TABLE_LIST *table, String *buff, + bool check_inherit); void init_fill_schema_files_row(TABLE* table); bool schema_table_store_record(THD *thd, TABLE *table); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index ef804fb7c5f..340ff3233e7 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1193,7 +1193,7 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len) views->view_suid = lex->create_view_suid; views->with_check = lex->create_view_check; - view_store_options(thd, views, &buff); + view_store_options4(thd, views, &buff, true); buff.append(STRING_WITH_LEN("VIEW ")); /* Test if user supplied a db (ie: we did not use thd->db) */ if (views->db && views->db[0] && From 0abde01f5e9a61cc482711b9b5f04a9815401ddb Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 29 Jul 2015 18:04:40 -0400 Subject: [PATCH 02/14] MDEV-8240 : Unknown option 'table_type' when using Connect Engine on MGC MariaDB Galera server's (MGC) handlerton & THD structures have some extra wsrep members as compared to MariaDB server. As a result, when plugins from packages, built along with MariaDB server like Connect & OQGraph are loaded and accessed by MGC, the objects may get initialized improperly. Fixed by moving the wsrep-additions to the end of the structure. --- sql/handler.h | 16 +++++----- sql/sql_class.h | 82 +++++++++++++++++++++++++------------------------ 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/sql/handler.h b/sql/handler.h index 09e412752a5..a2bc0212974 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1233,13 +1233,7 @@ struct handlerton enum handler_create_iterator_result (*create_iterator)(handlerton *hton, enum handler_iterator_type type, struct handler_iterator *fill_this_in); -#ifdef WITH_WSREP - int (*wsrep_abort_transaction)(handlerton *hton, THD *bf_thd, - THD *victim_thd, my_bool signal); - int (*wsrep_set_checkpoint)(handlerton *hton, const XID* xid); - int (*wsrep_get_checkpoint)(handlerton *hton, XID* xid); - void (*wsrep_fake_trx_id)(handlerton *hton, THD *thd); -#endif /* WITH_WSREP */ + /* Optional clauses in the CREATE/ALTER TABLE */ @@ -1352,6 +1346,14 @@ struct handlerton */ int (*discover_table_structure)(handlerton *hton, THD* thd, TABLE_SHARE *share, HA_CREATE_INFO *info); + +#ifdef WITH_WSREP + int (*wsrep_abort_transaction)(handlerton *hton, THD *bf_thd, + THD *victim_thd, my_bool signal); + int (*wsrep_set_checkpoint)(handlerton *hton, const XID* xid); + int (*wsrep_get_checkpoint)(handlerton *hton, XID* xid); + void (*wsrep_fake_trx_id)(handlerton *hton, THD *thd); +#endif /* WITH_WSREP */ }; diff --git a/sql/sql_class.h b/sql/sql_class.h index cae724e1a10..22c03aa33ae 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2783,46 +2783,7 @@ public: query_id_t first_query_id; } binlog_evt_union; -#ifdef WITH_WSREP - const bool wsrep_applier; /* dedicated slave applier thread */ - bool wsrep_applier_closing; /* applier marked to close */ - bool wsrep_client_thread; /* to identify client threads*/ - enum wsrep_exec_mode wsrep_exec_mode; - query_id_t wsrep_last_query_id; - enum wsrep_query_state wsrep_query_state; - enum wsrep_conflict_state wsrep_conflict_state; - mysql_mutex_t LOCK_wsrep_thd; - // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75 - // wsrep_seqno_t wsrep_trx_seqno; - wsrep_trx_meta_t wsrep_trx_meta; - uint32 wsrep_rand; - rpl_group_info* wsrep_rgi; - bool wsrep_converted_lock_session; - wsrep_ws_handle_t wsrep_ws_handle; -#ifdef WSREP_PROC_INFO - char wsrep_info[128]; /* string for dynamic proc info */ -#endif /* WSREP_PROC_INFO */ - ulong wsrep_retry_counter; // of autocommit - bool wsrep_PA_safe; - char* wsrep_retry_query; - size_t wsrep_retry_query_len; - enum enum_server_command wsrep_retry_command; - enum wsrep_consistency_check_mode - wsrep_consistency_check; - wsrep_stats_var* wsrep_status_vars; - int wsrep_mysql_replicated; - const char* wsrep_TOI_pre_query; /* a query to apply before - the actual TOI query */ - size_t wsrep_TOI_pre_query_len; - wsrep_po_handle_t wsrep_po_handle; - size_t wsrep_po_cnt; - my_bool wsrep_po_in_trans; -#ifdef GTID_SUPPORT - rpl_sid wsrep_po_sid; -#endif /* GTID_SUPPORT */ - void* wsrep_apply_format; - bool wsrep_apply_toi; /* applier processing in TOI */ -#endif /* WITH_WSREP */ + /** Internal parser state. Note that since the parser is not re-entrant, we keep only one parser @@ -3857,6 +3818,47 @@ public: return (temporary_tables || (rgi_slave && rgi_have_temporary_tables())); } + +#ifdef WITH_WSREP + const bool wsrep_applier; /* dedicated slave applier thread */ + bool wsrep_applier_closing; /* applier marked to close */ + bool wsrep_client_thread; /* to identify client threads*/ + enum wsrep_exec_mode wsrep_exec_mode; + query_id_t wsrep_last_query_id; + enum wsrep_query_state wsrep_query_state; + enum wsrep_conflict_state wsrep_conflict_state; + mysql_mutex_t LOCK_wsrep_thd; + // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75 + // wsrep_seqno_t wsrep_trx_seqno; + wsrep_trx_meta_t wsrep_trx_meta; + uint32 wsrep_rand; + rpl_group_info* wsrep_rgi; + bool wsrep_converted_lock_session; + wsrep_ws_handle_t wsrep_ws_handle; +#ifdef WSREP_PROC_INFO + char wsrep_info[128]; /* string for dynamic proc info */ +#endif /* WSREP_PROC_INFO */ + ulong wsrep_retry_counter; // of autocommit + bool wsrep_PA_safe; + char* wsrep_retry_query; + size_t wsrep_retry_query_len; + enum enum_server_command wsrep_retry_command; + enum wsrep_consistency_check_mode + wsrep_consistency_check; + wsrep_stats_var* wsrep_status_vars; + int wsrep_mysql_replicated; + const char* wsrep_TOI_pre_query; /* a query to apply before + the actual TOI query */ + size_t wsrep_TOI_pre_query_len; + wsrep_po_handle_t wsrep_po_handle; + size_t wsrep_po_cnt; + my_bool wsrep_po_in_trans; +#ifdef GTID_SUPPORT + rpl_sid wsrep_po_sid; +#endif /* GTID_SUPPORT */ + void* wsrep_apply_format; + bool wsrep_apply_toi; /* applier processing in TOI */ +#endif /* WITH_WSREP */ }; From 82cecb1c983737191804dfd170cafdf436158f80 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 31 Jul 2015 11:21:57 -0400 Subject: [PATCH 03/14] MDEV-8240 : Unknown option 'table_type' when using Connect Engine on MGC Fix for 'reorder' compiler warning. --- sql/sql_class.cc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 128961d95a4..6356ad095dc 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1068,7 +1068,15 @@ THD::THD() derived_tables_processing(FALSE), waiting_on_group_commit(FALSE), has_waiter(FALSE), spcont(NULL), + m_parser_state(NULL), +#if defined(ENABLED_DEBUG_SYNC) + debug_sync_control(0), +#endif /* defined(ENABLED_DEBUG_SYNC) */ + wait_for_commit_ptr(0), + main_da(0, false, false), + m_stmt_da(&main_da) #ifdef WITH_WSREP + , wsrep_applier(is_applier), wsrep_applier_closing(FALSE), wsrep_client_thread(0), @@ -1076,15 +1084,8 @@ THD::THD() wsrep_po_cnt(0), wsrep_po_in_trans(FALSE), wsrep_apply_format(0), - wsrep_apply_toi(false), + wsrep_apply_toi(false) #endif - m_parser_state(NULL), -#if defined(ENABLED_DEBUG_SYNC) - debug_sync_control(0), -#endif /* defined(ENABLED_DEBUG_SYNC) */ - wait_for_commit_ptr(0), - main_da(0, false, false), - m_stmt_da(&main_da) { ulong tmp; From 4c69dc8116950d6bf0b09bfbc31a86d89831a364 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 6 Aug 2015 00:36:40 -0400 Subject: [PATCH 04/14] MDEV#7501 : alter table exchange partition is not replicated in galera cluster Added logic to replicate ALTER TABLE EXCHANGE PARTITION to other nodes in the cluster. --- mysql-test/suite/galera/r/partition.result | 81 ++++++++++++++++++++++ mysql-test/suite/galera/t/partition.test | 63 +++++++++++++++++ sql/sql_partition_admin.cc | 18 ++++- 3 files changed, 161 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera/r/partition.result b/mysql-test/suite/galera/r/partition.result index 60fb2ed298d..dbd082347e4 100644 --- a/mysql-test/suite/galera/r/partition.result +++ b/mysql-test/suite/galera/r/partition.result @@ -20,4 +20,85 @@ pk i SELECT * FROM t1; pk i DROP TABLE t1; +# +# MDEV#7501 : alter table exchange partition is not replicated in +# galera cluster +# + +# On node_1 +CREATE TABLE test.t1 ( +i INT UNSIGNED NOT NULL AUTO_INCREMENT, +PRIMARY KEY (i) +) ENGINE=INNODB +PARTITION BY RANGE (i) +(PARTITION p1 VALUES LESS THAN (10) ENGINE = INNODB, +PARTITION p2 VALUES LESS THAN (20) ENGINE = INNODB, +PARTITION pMax VALUES LESS THAN MAXVALUE ENGINE = INNODB); +INSERT INTO test.t1 (i) VALUE (9),(19); +CREATE TABLE test.p1 LIKE test.t1; +ALTER TABLE test.p1 REMOVE PARTITIONING; +ALTER TABLE test.t1 EXCHANGE PARTITION p1 WITH TABLE test.p1; +SELECT * FROM test.t1; +i +19 +SELECT * FROM test.p1; +i +9 + +# On node_2 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(10) unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`i`) +) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY RANGE (i) +(PARTITION p1 VALUES LESS THAN (10) ENGINE = InnoDB, + PARTITION p2 VALUES LESS THAN (20) ENGINE = InnoDB, + PARTITION pMax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */ +SHOW CREATE TABLE p1; +Table Create Table +p1 CREATE TABLE `p1` ( + `i` int(10) unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`i`) +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1 +SELECT * FROM test.t1; +i +19 +SELECT * FROM test.p1; +i +9 + +# On node_1 +ALTER TABLE t1 TRUNCATE PARTITION p2; +SELECT * FROM test.t1; +i + +# On node_2 +SELECT * FROM test.t1; +i + +# On node_1 +ALTER TABLE t1 DROP PARTITION p2; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(10) unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY RANGE (i) +(PARTITION p1 VALUES LESS THAN (10) ENGINE = InnoDB, + PARTITION pMax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */ + +# On node_2 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(10) unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY RANGE (i) +(PARTITION p1 VALUES LESS THAN (10) ENGINE = InnoDB, + PARTITION pMax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */ +DROP TABLE t1, p1; # End of test diff --git a/mysql-test/suite/galera/t/partition.test b/mysql-test/suite/galera/t/partition.test index 048f35a9282..d6775fdc958 100644 --- a/mysql-test/suite/galera/t/partition.test +++ b/mysql-test/suite/galera/t/partition.test @@ -27,5 +27,68 @@ SELECT * FROM t1; # Cleanup DROP TABLE t1; + +--echo # +--echo # MDEV#7501 : alter table exchange partition is not replicated in +--echo # galera cluster +--echo # + +--echo +--echo # On node_1 +--connection node_1 + +CREATE TABLE test.t1 ( + i INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (i) + ) ENGINE=INNODB + PARTITION BY RANGE (i) + (PARTITION p1 VALUES LESS THAN (10) ENGINE = INNODB, + PARTITION p2 VALUES LESS THAN (20) ENGINE = INNODB, + PARTITION pMax VALUES LESS THAN MAXVALUE ENGINE = INNODB); + +INSERT INTO test.t1 (i) VALUE (9),(19); +CREATE TABLE test.p1 LIKE test.t1; +ALTER TABLE test.p1 REMOVE PARTITIONING; + +ALTER TABLE test.t1 EXCHANGE PARTITION p1 WITH TABLE test.p1; +SELECT * FROM test.t1; +SELECT * FROM test.p1; + +--echo +--echo # On node_2 +--connection node_2 + +SHOW CREATE TABLE t1; +SHOW CREATE TABLE p1; + +SELECT * FROM test.t1; +SELECT * FROM test.p1; + +--echo +--echo # On node_1 +--connection node_1 +ALTER TABLE t1 TRUNCATE PARTITION p2; +SELECT * FROM test.t1; + +--echo +--echo # On node_2 +--connection node_2 +SELECT * FROM test.t1; + +--echo +--echo # On node_1 +--connection node_1 +ALTER TABLE t1 DROP PARTITION p2; +SHOW CREATE TABLE t1; + +--echo +--echo # On node_2 +--connection node_2 +SHOW CREATE TABLE t1; + + +# Cleanup +DROP TABLE t1, p1; + --source include/galera_end.inc --echo # End of test diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index 029744b63f5..1d5cebfbbfd 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -530,6 +530,21 @@ bool Sql_cmd_alter_table_exchange_partition:: &alter_prelocking_strategy)) DBUG_RETURN(true); +#ifdef WITH_WSREP + /* Forward declaration */ + TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); + + if ((!thd->is_current_stmt_binlog_format_row() || + /* TODO: Do we really need to check for temp tables in this case? */ + !find_temporary_table(thd, table_list)) && + wsrep_to_isolation_begin(thd, table_list->db, table_list->table_name, + NULL)) + { + WSREP_WARN("ALTER TABLE EXCHANGE PARTITION isolation failure"); + DBUG_RETURN(TRUE); + } +#endif /* WITH_WSREP */ + part_table= table_list->table; swap_table= swap_table_list->table; @@ -764,6 +779,7 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd) DBUG_RETURN(TRUE); #ifdef WITH_WSREP + /* Forward declaration */ TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); if ((!thd->is_current_stmt_binlog_format_row() || @@ -772,7 +788,7 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd) thd, first_table->db, first_table->table_name, NULL) ) { - WSREP_WARN("ALTER TABLE isolation failure"); + WSREP_WARN("ALTER TABLE TRUNCATE PARTITION isolation failure"); DBUG_RETURN(TRUE); } #endif /* WITH_WSREP */ From e998dffde7af2ac8b751b7d4ad22fd4bf08489f9 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 12 Aug 2015 17:47:25 -0400 Subject: [PATCH 05/14] MDEV-8598 : Failed MySQL DDL commands and Galera replication RENAME TABLE, unlike other DDLs, was getting replicated before the access check was performed. As a result, the command could get get replicated and thus executed on other nodes, even if it fails on the originating node due to permission issues. Fixed by moving the logic to check user privileges before replicating the command. --- mysql-test/suite/galera/r/rename.result | 38 ++++++++++++++++++ mysql-test/suite/galera/t/rename.test | 52 +++++++++++++++++++++++++ sql/sql_parse.cc | 20 ++++++---- 3 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 mysql-test/suite/galera/r/rename.result create mode 100644 mysql-test/suite/galera/t/rename.test diff --git a/mysql-test/suite/galera/r/rename.result b/mysql-test/suite/galera/r/rename.result new file mode 100644 index 00000000000..b5a6c31a7f2 --- /dev/null +++ b/mysql-test/suite/galera/r/rename.result @@ -0,0 +1,38 @@ +# +# MDEV-8598 : Failed MySQL DDL commands and Galera replication +# +# On node 1 +USE test; +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUE(1); +SELECT * FROM t1; +i +1 +# Create a new user 'foo' with limited privileges +GRANT SELECT on test.* TO foo@localhost; +# Open connection to the 1st node using 'test_user1' user. +SELECT * FROM t1; +i +1 +# Following RENAME should not replicate to other node. +RENAME TABLE t1 TO t2; +ERROR 42000: DROP,ALTER command denied to user 'foo'@'localhost' for table 't1' +# On node 2 +USE test; +SELECT * FROM t1; +i +1 +# On node_1 +RENAME TABLE t1 TO t2; +SHOW TABLES; +Tables_in_test +t2 +# On node 2 +USE test; +SELECT * FROM t2; +i +1 +DROP USER foo@localhost; +DROP TABLE t2; +# End of tests diff --git a/mysql-test/suite/galera/t/rename.test b/mysql-test/suite/galera/t/rename.test new file mode 100644 index 00000000000..27811678bf5 --- /dev/null +++ b/mysql-test/suite/galera/t/rename.test @@ -0,0 +1,52 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--echo # +--echo # MDEV-8598 : Failed MySQL DDL commands and Galera replication +--echo # +--echo # On node 1 +--connection node_1 +USE test; +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUE(1); +SELECT * FROM t1; + +--echo # Create a new user 'foo' with limited privileges +GRANT SELECT on test.* TO foo@localhost; + +--echo # Open connection to the 1st node using 'test_user1' user. +--let $port_1= \$NODE_MYPORT_1 +--connect(foo_node_1,localhost,foo,,test,$port_1,) + +--connection foo_node_1 +SELECT * FROM t1; +--echo # Following RENAME should not replicate to other node. +--error ER_TABLEACCESS_DENIED_ERROR +RENAME TABLE t1 TO t2; + +--echo # On node 2 +--connection node_2 +USE test; +SELECT * FROM t1; + +--echo # On node_1 +--connection node_1 +RENAME TABLE t1 TO t2; +SHOW TABLES; + +--echo # On node 2 +--connection node_2 +USE test; +SELECT * FROM t2; + +# Cleanup +--connection node_1 +DROP USER foo@localhost; +DROP TABLE t2; + +--echo # End of tests + diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 499cda302b5..44f173e627a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -52,7 +52,7 @@ #include "sql_connect.h" // decrease_user_connections, // check_mqh, // reset_mqh -#include "sql_rename.h" // mysql_rename_table +#include "sql_rename.h" // mysql_rename_tables #include "sql_tablespace.h" // mysql_alter_tablespace #include "hostname.h" // hostname_cache_refresh #include "sql_acl.h" // *_ACL, check_grant, is_acl_user, @@ -127,7 +127,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables); static void sql_kill(THD *thd, ulong id, killed_state state); static void sql_kill_user(THD *thd, LEX_USER *user, killed_state state); static bool execute_show_status(THD *, TABLE_LIST *); -static bool execute_rename_table(THD *, TABLE_LIST *, TABLE_LIST *); +static bool check_rename_table(THD *, TABLE_LIST *, TABLE_LIST *); const char *any_db="*any*"; // Special symbol for check_access @@ -3055,8 +3055,12 @@ end_with_restore_list: case SQLCOM_RENAME_TABLE: { + if (check_rename_table(thd, first_table, all_tables)) + goto error; + WSREP_TO_ISOLATION_BEGIN(0, 0, first_table) - if (execute_rename_table(thd, first_table, all_tables)) + + if (mysql_rename_tables(thd, first_table, 0)) goto error; break; } @@ -5226,8 +5230,8 @@ static bool execute_show_status(THD *thd, TABLE_LIST *all_tables) } -static bool execute_rename_table(THD *thd, TABLE_LIST *first_table, - TABLE_LIST *all_tables) +static bool check_rename_table(THD *thd, TABLE_LIST *first_table, + TABLE_LIST *all_tables) { DBUG_ASSERT(first_table == all_tables && first_table != 0); TABLE_LIST *table; @@ -5241,7 +5245,7 @@ static bool execute_rename_table(THD *thd, TABLE_LIST *first_table, &table->next_local->grant.privilege, &table->next_local->grant.m_internal, 0, 0)) - return 1; + return true; TABLE_LIST old_list, new_list; /* we do not need initialize old_list and new_list because we will @@ -5254,10 +5258,10 @@ static bool execute_rename_table(THD *thd, TABLE_LIST *first_table, INSERT_ACL | CREATE_ACL) && check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, FALSE, 1, FALSE))) - return 1; + return true; } - return mysql_rename_tables(thd, first_table, 0); + return false; } From c18e0dab8a24db9d8f84fef328c27a28939a6ef5 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 14 Aug 2015 00:01:18 -0400 Subject: [PATCH 06/14] MDEV-8617: Multiple galera tests failures with --ps-protocol In galera cluster, when myisam replication is enabled (wsrep_replicate_myisam=ON), DML statements are replicated in open_tables(). However, in case of prepared statements, for an INSERT, open_tables() gets invoked twice. Once for COM_STMT_PREPARE (to validate and prepare INSERT) and later for COM_STMT_EXECUTE. As a result, the command gets replicated twice. Same happens for REPLACE, UPDATE and DELETE commands. Fixed by adding a check to not replicate during 'prepare' phase. Also changed the order of conditions to make it more efficient. Lastly, in order to support wsrep_dirty_reads, made changes to allow COM_STMT_XXX commands to continue past initial check even when wsrep is not ready. --- sql/sql_base.cc | 30 ++++++++++++++++-------------- sql/sql_class.h | 2 ++ sql/sql_parse.cc | 5 +++++ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index acf553b1041..f0596dd1fc6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5226,20 +5226,22 @@ restart: } } #ifdef WITH_WSREP - if ((thd->lex->sql_command== SQLCOM_INSERT || - thd->lex->sql_command== SQLCOM_INSERT_SELECT || - thd->lex->sql_command== SQLCOM_REPLACE || - thd->lex->sql_command== SQLCOM_REPLACE_SELECT || - thd->lex->sql_command== SQLCOM_UPDATE || - thd->lex->sql_command== SQLCOM_UPDATE_MULTI || - thd->lex->sql_command== SQLCOM_LOAD || - thd->lex->sql_command== SQLCOM_DELETE) && - wsrep_replicate_myisam && - (*start) && - (*start)->table && (*start)->table->file->ht->db_type == DB_TYPE_MYISAM) - { - WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); - } + if (wsrep_replicate_myisam && + (*start) && + (*start)->table && + (*start)->table->file->ht->db_type == DB_TYPE_MYISAM && + thd->get_command() != COM_STMT_PREPARE && + ((thd->lex->sql_command == SQLCOM_INSERT || + thd->lex->sql_command == SQLCOM_INSERT_SELECT || + thd->lex->sql_command == SQLCOM_REPLACE || + thd->lex->sql_command == SQLCOM_REPLACE_SELECT || + thd->lex->sql_command == SQLCOM_UPDATE || + thd->lex->sql_command == SQLCOM_UPDATE_MULTI || + thd->lex->sql_command == SQLCOM_LOAD || + thd->lex->sql_command == SQLCOM_DELETE))) + { + WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); + } error: #endif diff --git a/sql/sql_class.h b/sql/sql_class.h index 418c8043673..6deabb04f3d 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3076,6 +3076,8 @@ private: public: /** Overloaded to guard query/query_length fields */ virtual void set_statement(Statement *stmt); + inline enum enum_server_command get_command() const + { return command; } /** Assign a new value to thd->query and thd->query_id and mysys_var. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 44f173e627a..3629f3dd198 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -862,6 +862,11 @@ bool do_command(THD *thd) command != COM_SLEEP && command != COM_STATISTICS && command != COM_TIME && + command != COM_STMT_PREPARE && + command != COM_STMT_SEND_LONG_DATA && + command != COM_STMT_EXECUTE && + command != COM_STMT_RESET && + command != COM_STMT_CLOSE && command != COM_END ) { my_message(ER_UNKNOWN_COM_ERROR, From e996304189999eae8aeaa6995a80bf486833ed87 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 14 Aug 2015 01:31:38 -0400 Subject: [PATCH 07/14] MDEV-8617: Multiple galera tests failures with --ps-protocol (Additional fixes in 10.0-galera branch) * Reset THD's PS members before returning when node is not ready. * Update galera_suspend_slave.test --- mysql-test/suite/galera/t/galera_suspend_slave.test | 2 +- sql/sql_parse.cc | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera/t/galera_suspend_slave.test b/mysql-test/suite/galera/t/galera_suspend_slave.test index ac3fdf0ef40..236c65b73a7 100644 --- a/mysql-test/suite/galera/t/galera_suspend_slave.test +++ b/mysql-test/suite/galera/t/galera_suspend_slave.test @@ -30,7 +30,7 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; exit(0); EOF ---error ER_UNKNOWN_COM_ERROR,ER_LOCK_WAIT_TIMEOUT +--error ER_UNKNOWN_COM_ERROR,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK INSERT INTO t1 VALUES (1); --echo Resuming node_2 ... diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7643179b4c8..42ad69d84ec 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1075,6 +1075,12 @@ bool do_command(THD *thd) "WSREP has not yet prepared node for application use", MYF(0)); thd->protocol->end_statement(); + + /* Performance Schema Interface instrumentation end */ + MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); + thd->m_statement_psi= NULL; + thd->m_digest= NULL; + return_value= FALSE; goto out; } From 52f1543ef1e1dc48a26076788e18e223cb34d872 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 14 Aug 2015 01:37:21 -0400 Subject: [PATCH 08/14] Fix for a memory leak. --- sql/wsrep_mysqld.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 58b972d7ca3..5e6052dc2e4 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1199,6 +1199,7 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, uchar* buf(0); size_t buf_len(0); int buf_err; + int rc= 0; WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), thd->wsrep_exec_mode, thd->query() ); @@ -1238,7 +1239,6 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, { thd->wsrep_exec_mode= TOTAL_ORDER; wsrep_to_isolation++; - if (buf) my_free(buf); wsrep_keys_free(&key_arr); WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)wsrep_thd_trx_seqno(thd), thd->wsrep_exec_mode); @@ -1250,18 +1250,18 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_, ret, (thd->query()) ? thd->query() : "void"); my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check " "your wsrep connection state and retry the query."); - if (buf) my_free(buf); wsrep_keys_free(&key_arr); - return -1; + rc= -1; } else { /* non replicated DDL, affecting temporary tables only */ WSREP_DEBUG("TO isolation skipped for: %d, sql: %s." "Only temporary tables affected.", ret, (thd->query()) ? thd->query() : "void"); - return 1; + rc= 1; } - return 0; + if (buf) my_free(buf); + return rc; } static void wsrep_TOI_end(THD *thd) { From 5cf737c07a959fa3f03fb3c6d0a71ac442e59073 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 14 Aug 2015 02:46:32 -0400 Subject: [PATCH 09/14] MDEV-8464 : ALTER VIEW not replicated in some cases (Additional fix in 10.0-galera branch) THD's lex->definer initially holds "*current_user" for CURRENT_USER(). Use get_current_user() to get the real current user. --- sql/wsrep_mysqld.cc | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 5e6052dc2e4..cc8a6b64526 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1130,7 +1130,13 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len) buff.append(command[thd->lex->create_view_mode].str, command[thd->lex->create_view_mode].length); - if (!lex->definer) + LEX_USER *definer; + + if (lex->definer) + { + definer= get_current_user(thd, lex->definer); + } + else { /* DEFINER-clause is missing; we have to create default definer in @@ -1138,16 +1144,19 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len) If this is an ALTER VIEW then the current user should be set as the definer. */ + definer= create_default_definer(thd, false); + } - if (!(lex->definer= create_default_definer(thd, false))) - { - WSREP_WARN("view default definer issue"); - } + if (definer) + { + views->definer.user = definer->user; + views->definer.host = definer->host; + } else { + WSREP_ERROR("Failed to get DEFINER for VIEW."); + return 1; } views->algorithm = lex->create_view_algorithm; - views->definer.user = lex->definer->user; - views->definer.host = lex->definer->host; views->view_suid = lex->create_view_suid; views->with_check = lex->create_view_check; From fe757e006c676bc1cfb713f26fbd43e608531458 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 14 Aug 2015 13:45:52 -0400 Subject: [PATCH 10/14] Fix for some failing tests. --- mysql-test/r/innodb_load_xa_with_wsrep.result | 2 ++ mysql-test/suite/galera/suite.pm | 2 +- mysql-test/suite/innodb/r/innodb_uninstall.result | 4 ++++ mysql-test/suite/wsrep/suite.pm | 2 +- mysql-test/t/innodb_load_xa_with_wsrep.test | 3 +++ 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/innodb_load_xa_with_wsrep.result b/mysql-test/r/innodb_load_xa_with_wsrep.result index 6064dcd22d3..8b1e48bb8ca 100644 --- a/mysql-test/r/innodb_load_xa_with_wsrep.result +++ b/mysql-test/r/innodb_load_xa_with_wsrep.result @@ -16,3 +16,5 @@ mysqld-bin.000001 # Query # # use `test`; insert t1 values (2) mysqld-bin.000001 # Xid # # COMMIT /* XID */ drop table t1; uninstall plugin innodb; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 03bb2e85e81..d0147fd6309 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -33,7 +33,7 @@ push @::global_suppressions, qr(WSREP: last inactive check more than .* skipping check), qr(WSREP: SQL statement was ineffective), qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.), - qr|WSREP: access file\(gvwstate.dat\) failed\(No such file or directory\)|, + qr|WSREP: access file\(.*gvwstate.dat\) failed\(No such file or directory\)|, ); diff --git a/mysql-test/suite/innodb/r/innodb_uninstall.result b/mysql-test/suite/innodb/r/innodb_uninstall.result index 2064269a02e..d0270c1cf3e 100644 --- a/mysql-test/suite/innodb/r/innodb_uninstall.result +++ b/mysql-test/suite/innodb/r/innodb_uninstall.result @@ -1,4 +1,6 @@ install plugin innodb soname 'ha_innodb'; +Warnings: +Warning 1105 Cannot enable tc-log at run-time. XA features of InnoDB are disabled create table t1(a int not null primary key) engine=innodb; begin; insert into t1 values(1); @@ -11,6 +13,8 @@ Warnings: Warning 1620 Plugin is busy and will be uninstalled on shutdown drop table t1; install plugin innodb soname 'ha_innodb'; +Warnings: +Warning 1105 Cannot enable tc-log at run-time. XA features of InnoDB are disabled create table t2(a int not null primary key) engine=innodb; insert into t2 values(1); drop table t2; diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm index 33744a60ad8..1dbe1630a1b 100644 --- a/mysql-test/suite/wsrep/suite.pm +++ b/mysql-test/suite/wsrep/suite.pm @@ -27,7 +27,7 @@ push @::global_suppressions, qr(WSREP: Could not open saved state file for reading: ), qr(WSREP: option --wsrep-casual-reads is deprecated), qr(WSREP: --wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=0), - qr|WSREP: access file\(gvwstate.dat\) failed\(No such file or directory\)|, + qr|WSREP: access file\(.*gvwstate.dat\) failed\(No such file or directory\)|, ); $ENV{PATH}="$epath:$ENV{PATH}"; diff --git a/mysql-test/t/innodb_load_xa_with_wsrep.test b/mysql-test/t/innodb_load_xa_with_wsrep.test index 413faf54864..6755d209a02 100644 --- a/mysql-test/t/innodb_load_xa_with_wsrep.test +++ b/mysql-test/t/innodb_load_xa_with_wsrep.test @@ -17,3 +17,6 @@ commit; --source include/show_binlog_events.inc drop table t1; uninstall plugin innodb; + +--source include/restart_mysqld.inc + From 98bebad67274a87517a94b204cd8684a2e48d8c6 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 18 Aug 2015 17:03:28 -0400 Subject: [PATCH 11/14] Fix for a typo. --- mysql-test/suite/wsrep/suite.pm | 4 ++-- sql/mysqld.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm index 1dbe1630a1b..ec7a3e374f5 100644 --- a/mysql-test/suite/wsrep/suite.pm +++ b/mysql-test/suite/wsrep/suite.pm @@ -25,8 +25,8 @@ return "No my_print_defaults" unless $epath; push @::global_suppressions, ( qr(WSREP: Could not open saved state file for reading: ), - qr(WSREP: option --wsrep-casual-reads is deprecated), - qr(WSREP: --wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=0), + qr(WSREP: option --wsrep-causal-reads is deprecated), + qr(WSREP: --wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=0), qr|WSREP: access file\(.*gvwstate.dat\) failed\(No such file or directory\)|, ); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 357b62ff2a8..a59780f8f4f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8764,10 +8764,10 @@ static int get_options(int *argc_ptr, char ***argv_ptr) } if (global_system_variables.wsrep_causal_reads) { - WSREP_WARN("option --wsrep-casual-reads is deprecated"); + WSREP_WARN("option --wsrep-causal-reads is deprecated"); if (!(global_system_variables.wsrep_sync_wait & WSREP_SYNC_WAIT_BEFORE_READ)) { - WSREP_WARN("--wsrep-casual-reads=ON takes precedence over --wsrep-sync-wait=%u. " + WSREP_WARN("--wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=%u. " "WSREP_SYNC_WAIT_BEFORE_READ is on", global_system_variables.wsrep_sync_wait); global_system_variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ; From ccd39b2dd3315ce6a7844676907097325b39c0b8 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 20 Aug 2015 09:55:54 -0400 Subject: [PATCH 12/14] Backport partition tests from 10.0-galera. --- .../r/galera_var_load_data_splitting.result | 9 +++++ mysql-test/suite/galera/r/partition.result | 23 +++++++++++ .../t/galera_var_load_data_splitting.test | 38 +++++++++++++++++++ mysql-test/suite/galera/t/partition.test | 31 +++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 mysql-test/suite/galera/r/galera_var_load_data_splitting.result create mode 100644 mysql-test/suite/galera/r/partition.result create mode 100644 mysql-test/suite/galera/t/galera_var_load_data_splitting.test create mode 100644 mysql-test/suite/galera/t/partition.test diff --git a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result new file mode 100644 index 00000000000..db145fd1561 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result @@ -0,0 +1,9 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL wsrep_load_data_splitting = TRUE; +SELECT COUNT(*) = 95000 FROM t1; +COUNT(*) = 95000 +1 +wsrep_last_committed_diff +1 +SET GLOBAL wsrep_load_data_splitting = 1;; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/partition.result b/mysql-test/suite/galera/r/partition.result new file mode 100644 index 00000000000..60fb2ed298d --- /dev/null +++ b/mysql-test/suite/galera/r/partition.result @@ -0,0 +1,23 @@ +# +# MDEV#4953 Galera: DELETE from a partitioned table is not replicated +# +USE test; +CREATE TABLE t1 (pk INT PRIMARY KEY, i INT) ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; +INSERT INTO t1 VALUES (1,100), (2,200); +SELECT * FROM t1; +pk i +2 200 +1 100 +DELETE FROM t1; +SELECT * FROM t1; +pk i + +# On node_1 +SELECT * FROM t1; +pk i + +# On node_2 +SELECT * FROM t1; +pk i +DROP TABLE t1; +# End of test diff --git a/mysql-test/suite/galera/t/galera_var_load_data_splitting.test b/mysql-test/suite/galera/t/galera_var_load_data_splitting.test new file mode 100644 index 00000000000..0783dc897f8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_load_data_splitting.test @@ -0,0 +1,38 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $wsrep_load_data_splitting_orig = `SELECT @@wsrep_load_data_splitting` + +# Create a file for LOAD DATA with 95K entries +--perl +open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/galera_var_load_data_splitting.csv") or die; +foreach my $i (1..95000) { + print FILE "$i\n"; +} +EOF + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +# Record wsrep_last_committed as it was before LOAD DATA +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +SET GLOBAL wsrep_load_data_splitting = TRUE; +--disable_query_log +--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/galera_var_load_data_splitting.csv' INTO TABLE t1; +--enable_query_log + +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +SELECT COUNT(*) = 95000 FROM t1; + +# LOAD-ing 95K rows causes 10 commits to be registered +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 10 AS wsrep_last_committed_diff; +--enable_query_log + +--connection node_1 +--eval SET GLOBAL wsrep_load_data_splitting = $wsrep_load_data_splitting_orig; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/partition.test b/mysql-test/suite/galera/t/partition.test new file mode 100644 index 00000000000..048f35a9282 --- /dev/null +++ b/mysql-test/suite/galera/t/partition.test @@ -0,0 +1,31 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_partition.inc + +--echo # +--echo # MDEV#4953 Galera: DELETE from a partitioned table is not replicated +--echo # + +USE test; +CREATE TABLE t1 (pk INT PRIMARY KEY, i INT) ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; +INSERT INTO t1 VALUES (1,100), (2,200); +SELECT * FROM t1; + +DELETE FROM t1; +SELECT * FROM t1; + +--echo +--echo # On node_1 +--connection node_1 +SELECT * FROM t1; + +--echo +--echo # On node_2 +--connection node_2 +SELECT * FROM t1; + +# Cleanup +DROP TABLE t1; + +--source include/galera_end.inc +--echo # End of test From 4ee28865f67c980848bb62f0009440be73ebee7c Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Thu, 20 Aug 2015 20:55:52 -0400 Subject: [PATCH 13/14] MDEV-5146 : Bulk loads into partitioned table not working When wsrep is enabled, for any update on innodb tables, the corresponding keys are appended to galera's transaction writeset (wsrep_append_keys()). However, for LOAD DATA, this got skipped if binary logging was disabled or it was non-ROW based. As a result, while the updates from LOAD DATA on non-partitioned tables replicated fine as wsrep implicitly enables binary logging (if not enabled, explicitly), the same did not work on partitioned tables as for partitioned tables the binary logging gets disabled temporarily (ha_partition::write_row()). Fixed by removing the unwanted conditions from the check. Also backported some changes from 10.0-galera to make sure wsrep_load_data_splitting affects LOAD DATA commands only. --- mysql-test/suite/galera/r/partition.result | 36 +++++++ mysql-test/suite/galera/t/partition.test | 113 +++++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 31 ++++-- storage/xtradb/handler/ha_innodb.cc | 31 ++++-- 4 files changed, 191 insertions(+), 20 deletions(-) diff --git a/mysql-test/suite/galera/r/partition.result b/mysql-test/suite/galera/r/partition.result index 60fb2ed298d..379b82fabf8 100644 --- a/mysql-test/suite/galera/r/partition.result +++ b/mysql-test/suite/galera/r/partition.result @@ -20,4 +20,40 @@ pk i SELECT * FROM t1; pk i DROP TABLE t1; +# +# MDEV-5146: Bulk loads into partitioned table not working +# +# Case 1: wsrep_load_data_splitting = ON & LOAD DATA with 20002 +# entries. +SET GLOBAL wsrep_load_data_splitting = ON; +CREATE TABLE t1 (pk INT PRIMARY KEY) +ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; +SELECT COUNT(*) = 20002 FROM t1; +COUNT(*) = 20002 +1 +wsrep_last_committed_diff +1 +DROP TABLE t1; +# Case 2: wsrep_load_data_splitting = ON & LOAD DATA with 101 entries. +SET GLOBAL wsrep_load_data_splitting = ON; +CREATE TABLE t1 (pk INT PRIMARY KEY) +ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; +SELECT COUNT(*) = 101 FROM t1; +COUNT(*) = 101 +1 +wsrep_last_committed_diff +1 +DROP TABLE t1; +# Case 3: wsrep_load_data_splitting = OFF & LOAD DATA with 20002 +# entries. +SET GLOBAL wsrep_load_data_splitting = OFF; +CREATE TABLE t1 (pk INT PRIMARY KEY) +ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; +SELECT COUNT(*) = 20002 FROM t1; +COUNT(*) = 20002 +1 +wsrep_last_committed_diff +1 +DROP TABLE t1; +SET GLOBAL wsrep_load_data_splitting = 1;; # End of test diff --git a/mysql-test/suite/galera/t/partition.test b/mysql-test/suite/galera/t/partition.test index 048f35a9282..e4775e1e730 100644 --- a/mysql-test/suite/galera/t/partition.test +++ b/mysql-test/suite/galera/t/partition.test @@ -27,5 +27,118 @@ SELECT * FROM t1; # Cleanup DROP TABLE t1; +--echo # +--echo # MDEV-5146: Bulk loads into partitioned table not working +--echo # + +# Create 2 files with 20002 & 101 entries in each. +--perl +open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/mdev-5146-1.dat") or die; +foreach my $i (1..20002) { + print FILE "$i\n"; +} + +open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/mdev-5146-2.dat") or die; +foreach my $i (1..101) { + print FILE "$i\n"; +} +EOF + +--connection node_1 + +--let $wsrep_load_data_splitting_orig = `SELECT @@wsrep_load_data_splitting` + +--echo # Case 1: wsrep_load_data_splitting = ON & LOAD DATA with 20002 +--echo # entries. + +SET GLOBAL wsrep_load_data_splitting = ON; + +CREATE TABLE t1 (pk INT PRIMARY KEY) + ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; + +# Record wsrep_last_committed as it was before LOAD DATA +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +--disable_query_log +--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/mdev-5146-1.dat' INTO TABLE t1; +--enable_query_log + +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +--connection node_2 +SELECT COUNT(*) = 20002 FROM t1; + +# LOAD-ing 20002 rows causes 3 commits to be registered +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 3 AS wsrep_last_committed_diff; +--enable_query_log + +DROP TABLE t1; + +--echo # Case 2: wsrep_load_data_splitting = ON & LOAD DATA with 101 entries. + +--connection node_1 + +SET GLOBAL wsrep_load_data_splitting = ON; + +CREATE TABLE t1 (pk INT PRIMARY KEY) + ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; + +# Record wsrep_last_committed as it was before LOAD DATA +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +--disable_query_log +--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/mdev-5146-2.dat' INTO TABLE t1; +--enable_query_log + +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +--connection node_2 +SELECT COUNT(*) = 101 FROM t1; + +# LOAD-ing 101 rows causes 1 commit to be registered +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--enable_query_log + +DROP TABLE t1; + +--echo # Case 3: wsrep_load_data_splitting = OFF & LOAD DATA with 20002 +--echo # entries. + +--connection node_1 + +SET GLOBAL wsrep_load_data_splitting = OFF; + +CREATE TABLE t1 (pk INT PRIMARY KEY) + ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; + +# Record wsrep_last_committed as it was before LOAD DATA +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +--disable_query_log +--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/mdev-5146-1.dat' INTO TABLE t1; +--enable_query_log + +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +--connection node_2 +SELECT COUNT(*) = 20002 FROM t1; + +# LOAD-ing 20002 rows causes 1 commit to be registered +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--enable_query_log + +DROP TABLE t1; + +--connection node_1 +# Restore the original value +--eval SET GLOBAL wsrep_load_data_splitting = $wsrep_load_data_splitting_orig; + +# Cleanup +remove_file '$MYSQLTEST_VARDIR/tmp/mdev-5146-1.dat'; +remove_file '$MYSQLTEST_VARDIR/tmp/mdev-5146-2.dat'; + --source include/galera_end.inc --echo # End of test diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 773e74e9ab0..0fce4e4c4f6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5753,7 +5753,12 @@ no_commit: ; } else if (src_table == prebuilt->table) { #ifdef WITH_WSREP - if (wsrep_on(user_thd)) { + if (wsrep_on(user_thd) && + wsrep_load_data_splitting && + sql_command == SQLCOM_LOAD && + !thd_test_options(user_thd, + OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + { switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) { case WSREP_TRX_OK: @@ -5780,7 +5785,12 @@ no_commit: prebuilt->sql_stat_start = TRUE; } else { #ifdef WITH_WSREP - if (wsrep_on(user_thd)) { + if (wsrep_on(user_thd) && + wsrep_load_data_splitting && + sql_command == SQLCOM_LOAD && + !thd_test_options(user_thd, + OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + { switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) { case WSREP_TRX_OK: @@ -5990,14 +6000,15 @@ report_error: prebuilt->table->flags, user_thd); #ifdef WITH_WSREP - if (!error_result && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && - wsrep_on(user_thd) && !wsrep_consistency_check(user_thd) && - (sql_command != SQLCOM_LOAD || - thd_binlog_format(user_thd) == BINLOG_FORMAT_ROW)) { - - if (wsrep_append_keys(user_thd, false, record, NULL)) { - DBUG_PRINT("wsrep", ("row key failed")); - error_result = HA_ERR_INTERNAL_ERROR; + if (!error_result && + wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd) && + !wsrep_consistency_check(user_thd)) + { + if (wsrep_append_keys(user_thd, false, record, NULL)) + { + DBUG_PRINT("wsrep", ("row key failed")); + error_result = HA_ERR_INTERNAL_ERROR; goto wsrep_error; } } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 49c9790c435..3ae440c8cf7 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -6717,7 +6717,12 @@ no_commit: ; } else if (src_table == prebuilt->table) { #ifdef WITH_WSREP - if (wsrep_on(user_thd)) { + if (wsrep_on(user_thd) && + wsrep_load_data_splitting && + sql_command == SQLCOM_LOAD && + !thd_test_options(user_thd, + OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + { switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) { case WSREP_TRX_OK: @@ -6744,7 +6749,12 @@ no_commit: prebuilt->sql_stat_start = TRUE; } else { #ifdef WITH_WSREP - if (wsrep_on(user_thd)) { + if (wsrep_on(user_thd) && + wsrep_load_data_splitting && + sql_command == SQLCOM_LOAD && + !thd_test_options(user_thd, + OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + { switch (wsrep_run_wsrep_commit(user_thd, wsrep_hton, 1)) { case WSREP_TRX_OK: @@ -6960,14 +6970,15 @@ report_error: prebuilt->table->flags, user_thd); #ifdef WITH_WSREP - if (!error_result && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && - wsrep_on(user_thd) && !wsrep_consistency_check(user_thd) && - (sql_command != SQLCOM_LOAD || - thd_binlog_format(user_thd) == BINLOG_FORMAT_ROW)) { - - if (wsrep_append_keys(user_thd, false, record, NULL)) { - DBUG_PRINT("wsrep", ("row key failed")); - error_result = HA_ERR_INTERNAL_ERROR; + if (!error_result && + wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd) && + !wsrep_consistency_check(user_thd)) + { + if (wsrep_append_keys(user_thd, false, record, NULL)) + { + DBUG_PRINT("wsrep", ("row key failed")); + error_result = HA_ERR_INTERNAL_ERROR; goto wsrep_error; } } From 472d66320d8538f2d1850bb50caceed18181024a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Sat, 22 Aug 2015 01:18:02 -0400 Subject: [PATCH 14/14] MDEV-8149: Random mtr test failures during warning check Do not replicate commands from check-warnings.test to other nodes in the cluster. --- mysql-test/include/check-warnings.test | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mysql-test/include/check-warnings.test b/mysql-test/include/check-warnings.test index 3a26f7eecb1..cd3fa0b0153 100644 --- a/mysql-test/include/check-warnings.test +++ b/mysql-test/include/check-warnings.test @@ -11,6 +11,10 @@ # Don't write these queries to binlog set SQL_LOG_BIN=0; +# Do not replicate updates to other galera nodes +--error 0,1193 +set WSREP_ON=0; + # Turn off any debug crashes, allow the variable to be # non existent in release builds --error 0,1193