diff options
-rw-r--r-- | mysql-test/suite/galera/r/galera_can_run_toi.result | 6 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/galera_strict_require_innodb.result | 92 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/galera_strict_require_primary_key.result | 86 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_can_run_toi.test | 4 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_strict_require_innodb.test | 95 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_strict_require_primary_key.test | 90 | ||||
-rw-r--r-- | sql/sql_base.cc | 37 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 267 | ||||
-rw-r--r-- | sql/wsrep_mysqld.h | 5 |
9 files changed, 638 insertions, 44 deletions
diff --git a/mysql-test/suite/galera/r/galera_can_run_toi.result b/mysql-test/suite/galera/r/galera_can_run_toi.result index 6a7078b93a5..fb2fa6675ff 100644 --- a/mysql-test/suite/galera/r/galera_can_run_toi.result +++ b/mysql-test/suite/galera/r/galera_can_run_toi.result @@ -26,9 +26,7 @@ SELECT @@default_storage_engine; @@default_storage_engine MyISAM SET GLOBAL wsrep_replicate_myisam=OFF; -SET GLOBAL wsrep_strict_ddl=ON; -Warnings: -Warning 1287 '@@wsrep_strict_ddl' is deprecated and will be removed in a future release. Please use '@@wsrep_mode=STRICT_REPLICATION' instead +SET GLOBAL wsrep_mode=STRICT_REPLICATION; CREATE TABLE t3 (c1 VARCHAR(10)) ENGINE=InnoDB; ALTER TABLE t3 ENGINE=NonExistentEngine; ERROR HY000: Galera replication not supported @@ -38,5 +36,3 @@ t3 CREATE TABLE `t3` ( `c1` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t3; -Warnings: -Warning 1287 '@@wsrep_strict_ddl' is deprecated and will be removed in a future release. Please use '@@wsrep_mode=STRICT_REPLICATION' instead diff --git a/mysql-test/suite/galera/r/galera_strict_require_innodb.result b/mysql-test/suite/galera/r/galera_strict_require_innodb.result new file mode 100644 index 00000000000..0367a9e0cf7 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_strict_require_innodb.result @@ -0,0 +1,92 @@ +connection node_2; +connection node_1; +call mtr.add_suppression("WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine .*"); +CREATE TABLE t1(a int NOT NULL PRIMARY KEY, b varchar(50)) ENGINE=INNODB; +CREATE TABLE t2(a int NOT NULL PRIMARY KEY, b varchar(50)) ENGINE=MYISAM; +CREATE TABLE t3(a int NOT NULL PRIMARY KEY, b varchar(50)) ENGINE=ARIA; +CREATE TABLE t4(a int NOT NULL PRIMARY KEY, b varchar(50)) ENGINE=MEMORY; +SET GLOBAL wsrep_replicate_myisam=ON; +SET GLOBAL log_warnings=2; +SET GLOBAL wsrep_mode= STRICT_REPLICATION; +INSERT INTO t1 values (1,'innodb1'); +INSERT INTO t2 values (1,'myisam1'); +INSERT INTO t3 values (1,'aria1'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine Aria for table 'test'.'t3' is not supported in Galera +INSERT INTO t4 values (1,'memory1'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine MEMORY for table 'test'.'t4' is not supported in Galera +SET GLOBAL wsrep_replicate_myisam=OFF; +INSERT INTO t2 values (2,'myisam2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine MyISAM for table 'test'.'t2' is not supported in Galera +SET GLOBAL log_warnings=1; +INSERT INTO t1 values (2,'innodb2'); +INSERT INTO t2 values (3,'myisam3'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine MyISAM for table 'test'.'t2' is not supported in Galera +INSERT INTO t3 values (2,'aria2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine Aria for table 'test'.'t3' is not supported in Galera +INSERT INTO t4 values (2,'memory2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine MEMORY for table 'test'.'t4' is not supported in Galera +include/assert_grep.inc [WSREP: wsrep_mode = STRICT_REPLICATION enabled.] +SET GLOBAL log_warnings=2; +INSERT INTO t2 values (4,'myisam3'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine MyISAM for table 'test'.'t2' is not supported in Galera +INSERT INTO t3 values (4,'aria2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine Aria for table 'test'.'t3' is not supported in Galera +INSERT INTO t4 values (4,'memory2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine MEMORY for table 'test'.'t4' is not supported in Galera +INSERT INTO t2 values (5,'myisam3'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine MyISAM for table 'test'.'t2' is not supported in Galera +INSERT INTO t3 values (5,'aria2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine Aria for table 'test'.'t3' is not supported in Galera +INSERT INTO t4 values (5,'memory2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine MEMORY for table 'test'.'t4' is not supported in Galera +INSERT INTO t2 values (6,'myisam3'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine MyISAM for table 'test'.'t2' is not supported in Galera +INSERT INTO t3 values (6,'aria2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine Aria for table 'test'.'t3' is not supported in Galera +INSERT INTO t4 values (6,'memory2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine MEMORY for table 'test'.'t4' is not supported in Galera +SELECT COUNT(*) AS EXPECT_2 FROM t1; +EXPECT_2 +2 +SELECT COUNT(*) AS EXPECT_6 FROM t2; +EXPECT_6 +6 +SELECT COUNT(*) AS EXPECT_5 FROM t3; +EXPECT_5 +5 +SELECT COUNT(*) AS EXPECT_5 FROM t4; +EXPECT_5 +5 +connection node_2; +SELECT COUNT(*) AS EXPECT_2 FROM t1; +EXPECT_2 +2 +SELECT COUNT(*) AS EXPECT_1 FROM t2; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_0 FROM t3; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_0 FROM t4; +EXPECT_0 +0 +connection node_1; +SET GLOBAL wsrep_mode= DEFAULT; +DROP TABLE t1,t2,t3,t4; +include/assert_grep.inc [WSREP: wsrep_mode = STRICT_REPLICATION enabled.] +include/assert_grep.inc [WSREP: Suppressing warnings of type 'WSREP_REQUIRE_INNODB' for up to 300 seconds because of flooding] diff --git a/mysql-test/suite/galera/r/galera_strict_require_primary_key.result b/mysql-test/suite/galera/r/galera_strict_require_primary_key.result new file mode 100644 index 00000000000..bc644851b3e --- /dev/null +++ b/mysql-test/suite/galera/r/galera_strict_require_primary_key.result @@ -0,0 +1,86 @@ +connection node_2; +connection node_1; +call mtr.add_suppression("WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table .*"); +CREATE TABLE t1(a int, b varchar(50)) ENGINE=INNODB; +CREATE TABLE t2(a int, b varchar(50)) ENGINE=MYISAM; +CREATE TABLE t3(a int, b varchar(50)) ENGINE=MEMORY; +SET GLOBAL wsrep_replicate_myisam=ON; +SET GLOBAL log_warnings=2; +SET GLOBAL wsrep_mode= REQUIRED_PRIMARY_KEY; +INSERT INTO t1 values (1,'test1'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t2 values (1,'myisam1'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t2' should have PRIMARY KEY defined. +INSERT INTO t3 values (1,'memory'); +SET GLOBAL wsrep_replicate_myisam=OFF; +INSERT INTO t2 values (2,'mysam2'); +INSERT INTO t1 values (2,'test2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (3,'test3'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (4,'test4'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (5,'test5'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +SET GLOBAL log_warnings=1; +INSERT INTO t1 values (21,'not1'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (22,'not2'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +include/assert_grep.inc [WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled.] +SET GLOBAL log_warnings=2; +INSERT INTO t1 values (6,'test6'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (7,'test7'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (8,'test8'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (9,'test9'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (10,'test10'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (11,'test11'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (12,'test12'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +INSERT INTO t1 values (13,'test13'); +Warnings: +Warning 1290 WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table 'test'.'t1' should have PRIMARY KEY defined. +SELECT COUNT(*) AS EXPECT_15 FROM t1; +EXPECT_15 +15 +SELECT COUNT(*) AS EXPECT_2 FROM t2; +EXPECT_2 +2 +SELECT COUNT(*) AS EXPECT_1 FROM t3; +EXPECT_1 +1 +connection node_2; +SELECT COUNT(*) AS EXPECT_15 FROM t1; +EXPECT_15 +15 +SELECT COUNT(*) AS EXPECT_1 FROM t2; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_0 FROM t3; +EXPECT_0 +0 +connection node_1; +DROP TABLE t1,t2,t3; +include/assert_grep.inc [WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled.] +include/assert_grep.inc [WSREP: Suppressing warnings of type 'WSREP_REQUIRE_PRIMARY_KEY' for up to 300 seconds because of flooding] diff --git a/mysql-test/suite/galera/t/galera_can_run_toi.test b/mysql-test/suite/galera/t/galera_can_run_toi.test index a0087be4304..060ea887692 100644 --- a/mysql-test/suite/galera/t/galera_can_run_toi.test +++ b/mysql-test/suite/galera/t/galera_can_run_toi.test @@ -19,7 +19,7 @@ SET sql_mode=''; SET SESSION default_storage_engine=MyISAM; SELECT @@default_storage_engine; SET GLOBAL wsrep_replicate_myisam=OFF; -SET GLOBAL wsrep_strict_ddl=ON; +SET GLOBAL wsrep_mode=STRICT_REPLICATION; CREATE TABLE t3 (c1 VARCHAR(10)) ENGINE=InnoDB; --error ER_GALERA_REPLICATION_NOT_SUPPORTED ALTER TABLE t3 ENGINE=NonExistentEngine; @@ -30,5 +30,5 @@ DROP TABLE t3; SET GLOBAL sql_mode=default; SET GLOBAL default_storage_engine=default; SET GLOBAL wsrep_replicate_myisam=default; -SET GLOBAL wsrep_strict_ddl=default; +SET GLOBAL wsrep_mode=default; --enable_query_log diff --git a/mysql-test/suite/galera/t/galera_strict_require_innodb.test b/mysql-test/suite/galera/t/galera_strict_require_innodb.test new file mode 100644 index 00000000000..b4fe74d3406 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_strict_require_innodb.test @@ -0,0 +1,95 @@ +# +# Write a warning to error log if Galera replicates table with storage engine +# not supported by Galera +# +# For MyISAM +# * push warning to client if wsrep_mode == STRICT_REPLICATION and wsrep_replicate_myisam=off +# * push warning to error log if log_warnings > 1 +# For Memory +# * push warning to client if wsrep_mode == STRICT_REPLICATION +# * push warning to error log if log_warnings > 1 +# ( Note here Aria and case wsrep_replicate_aria=ON) +# +# In both cases apply flood control if > 10 same warning +# +--source include/galera_cluster.inc +--source include/have_aria.inc + +call mtr.add_suppression("WSREP: wsrep_mode = STRICT_REPLICATION enabled. Storage engine .*"); + +CREATE TABLE t1(a int NOT NULL PRIMARY KEY, b varchar(50)) ENGINE=INNODB; +CREATE TABLE t2(a int NOT NULL PRIMARY KEY, b varchar(50)) ENGINE=MYISAM; +CREATE TABLE t3(a int NOT NULL PRIMARY KEY, b varchar(50)) ENGINE=ARIA; +CREATE TABLE t4(a int NOT NULL PRIMARY KEY, b varchar(50)) ENGINE=MEMORY; + +SET GLOBAL wsrep_replicate_myisam=ON; +SET GLOBAL log_warnings=2; +SET GLOBAL wsrep_mode= STRICT_REPLICATION; + +INSERT INTO t1 values (1,'innodb1'); +INSERT INTO t2 values (1,'myisam1'); +INSERT INTO t3 values (1,'aria1'); +INSERT INTO t4 values (1,'memory1'); + +SET GLOBAL wsrep_replicate_myisam=OFF; +INSERT INTO t2 values (2,'myisam2'); + +SET GLOBAL log_warnings=1; +INSERT INTO t1 values (2,'innodb2'); +INSERT INTO t2 values (3,'myisam3'); +INSERT INTO t3 values (2,'aria2'); +INSERT INTO t4 values (2,'memory2'); + +# test flood control +--let $assert_count = 3 +--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_text = WSREP: wsrep_mode = STRICT_REPLICATION enabled. +--let $assert_select = WSREP: wsrep_mode = STRICT_REPLICATION enabled. +--source include/assert_grep.inc + +SET GLOBAL log_warnings=2; +INSERT INTO t2 values (4,'myisam3'); +INSERT INTO t3 values (4,'aria2'); +INSERT INTO t4 values (4,'memory2'); +INSERT INTO t2 values (5,'myisam3'); +INSERT INTO t3 values (5,'aria2'); +INSERT INTO t4 values (5,'memory2'); +INSERT INTO t2 values (6,'myisam3'); +INSERT INTO t3 values (6,'aria2'); +INSERT INTO t4 values (6,'memory2'); + +SELECT COUNT(*) AS EXPECT_2 FROM t1; +SELECT COUNT(*) AS EXPECT_6 FROM t2; +SELECT COUNT(*) AS EXPECT_5 FROM t3; +SELECT COUNT(*) AS EXPECT_5 FROM t4; + +--connection node_2 +SELECT COUNT(*) AS EXPECT_2 FROM t1; +SELECT COUNT(*) AS EXPECT_1 FROM t2; +SELECT COUNT(*) AS EXPECT_0 FROM t3; +SELECT COUNT(*) AS EXPECT_0 FROM t4; + +--connection node_1 +SET GLOBAL wsrep_mode= DEFAULT; +DROP TABLE t1,t2,t3,t4; + +# +# Verify no flood +# +--let $assert_count = 10 +--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_text = WSREP: wsrep_mode = STRICT_REPLICATION enabled. +--let $assert_select = WSREP: wsrep_mode = STRICT_REPLICATION enabled. +--source include/assert_grep.inc +--let $assert_count = 1 +--let $assert_text = WSREP: Suppressing warnings of type 'WSREP_REQUIRE_INNODB' for up to 300 seconds because of flooding +--let $assert_select = WSREP: Suppressing warnings of type 'WSREP_REQUIRE_INNODB' for up to 300 seconds because of flooding +--source include/assert_grep.inc + +# reset env +--disable_query_log +SET GLOBAL wsrep_replicate_myisam=DEFAULT; +SET GLOBAL log_warnings=DEFAULT; +SET GLOBAL wsrep_mode=DEFAULT; +--disable_query_log + diff --git a/mysql-test/suite/galera/t/galera_strict_require_primary_key.test b/mysql-test/suite/galera/t/galera_strict_require_primary_key.test new file mode 100644 index 00000000000..3a94c408fb6 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_strict_require_primary_key.test @@ -0,0 +1,90 @@ +# +# Write a warning to error log if Galera replicates table with no primary key +# +# For InnoDB +# * push warning to client if wsrep_mode == REQUIRED_PRIMARY_KEY +# * push warning to error log if log_warnings > 1 +# For MyIsam +# * push warning if wsrep_replicate_myisam=ON +# +# In both cases apply flood control if > 10 same warning +# +--source include/galera_cluster.inc + +call mtr.add_suppression("WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. Table .*"); + +CREATE TABLE t1(a int, b varchar(50)) ENGINE=INNODB; +CREATE TABLE t2(a int, b varchar(50)) ENGINE=MYISAM; +CREATE TABLE t3(a int, b varchar(50)) ENGINE=MEMORY; + +SET GLOBAL wsrep_replicate_myisam=ON; +SET GLOBAL log_warnings=2; +SET GLOBAL wsrep_mode= REQUIRED_PRIMARY_KEY; + +INSERT INTO t1 values (1,'test1'); +INSERT INTO t2 values (1,'myisam1'); +INSERT INTO t3 values (1,'memory'); + +SET GLOBAL wsrep_replicate_myisam=OFF; +INSERT INTO t2 values (2,'mysam2'); + +# test flood control +INSERT INTO t1 values (2,'test2'); +INSERT INTO t1 values (3,'test3'); +INSERT INTO t1 values (4,'test4'); +INSERT INTO t1 values (5,'test5'); + +# these should not write warning to error log +SET GLOBAL log_warnings=1; +INSERT INTO t1 values (21,'not1'); +INSERT INTO t1 values (22,'not2'); + +--let $assert_count = 6 +--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_text = WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. +--let $assert_select = WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. +--source include/assert_grep.inc + +# force flood +SET GLOBAL log_warnings=2; +INSERT INTO t1 values (6,'test6'); +INSERT INTO t1 values (7,'test7'); +INSERT INTO t1 values (8,'test8'); +INSERT INTO t1 values (9,'test9'); +INSERT INTO t1 values (10,'test10'); +INSERT INTO t1 values (11,'test11'); +INSERT INTO t1 values (12,'test12'); +INSERT INTO t1 values (13,'test13'); + +SELECT COUNT(*) AS EXPECT_15 FROM t1; +SELECT COUNT(*) AS EXPECT_2 FROM t2; +SELECT COUNT(*) AS EXPECT_1 FROM t3; + +--connection node_2 +SELECT COUNT(*) AS EXPECT_15 FROM t1; +SELECT COUNT(*) AS EXPECT_1 FROM t2; +SELECT COUNT(*) AS EXPECT_0 FROM t3; + +--connection node_1 +DROP TABLE t1,t2,t3; + +# +# Verify warning is on error log and check that no flood +# +--let $assert_count = 9 +--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_text = WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. +--let $assert_select = WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. +--source include/assert_grep.inc +--let $assert_count = 1 +--let $assert_text = WSREP: Suppressing warnings of type 'WSREP_REQUIRE_PRIMARY_KEY' for up to 300 seconds because of flooding +--let $assert_select = WSREP: Suppressing warnings of type 'WSREP_REQUIRE_PRIMARY_KEY' for up to 300 seconds because of flooding +--source include/assert_grep.inc + +# reset env +--disable_query_log +SET GLOBAL wsrep_replicate_myisam=DEFAULT; +SET GLOBAL log_warnings=DEFAULT; +SET GLOBAL wsrep_mode=DEFAULT; +--disable_query_log + diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 623c0eff5b9..bfbf688c932 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4431,13 +4431,16 @@ restart: tbl->reginfo.lock_type= tables->lock_type; } #ifdef WITH_WSREP - /* + /* At this point we have SE associated with table so we can check wsrep_mode rules at this point. */ - if (WSREP(thd) && + if (WSREP(thd) && wsrep_thd_is_local(thd) && - !wsrep_check_mode_after_open_table(thd, tbl->file->ht->db_type)) + tbl && + tables == *start && + !wsrep_check_mode_after_open_table(thd, + tbl->file->ht, tables)) { error= TRUE; goto error; @@ -4445,35 +4448,7 @@ restart: #endif } -#ifdef WITH_WSREP - if (WSREP(thd) && - wsrep_replicate_myisam && - (*start) && - (*start)->table && - (*start)->table->file->ht == myisam_hton && - wsrep_thd_is_local(thd) && - !is_stat_table(&(*start)->db, &(*start)->alias) && - 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_before_rollback(thd, true); - wsrep_after_rollback(thd, true); - wsrep_after_statement(thd); - WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); - } -#endif /* WITH_WSREP */ - error: -#ifdef WITH_WSREP -wsrep_error_label: -#endif THD_STAGE_INFO(thd, stage_after_opening_tables); thd_proc_info(thd, 0); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 9353aa82540..b1eb68d52fd 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -24,6 +24,7 @@ #include <sql_class.h> #include <sql_parse.h> #include <sql_base.h> /* find_temporary_table() */ +#include <sql_statistics.h> /* is_stat_table() */ #include "slave.h" #include "rpl_mi.h" #include "sql_repl.h" @@ -1169,15 +1170,273 @@ bool wsrep_check_mode (enum_wsrep_mode mask) return wsrep_mode & mask; } -bool wsrep_check_mode_after_open_table (THD *thd, legacy_db_type db_type) +//seconds after which the limit warnings suppression will be activated +#define WSREP_WARNING_ACTIVATION_TIMEOUT 5*60 +//number of limit warnings after which the suppression will be activated +#define WSREP_WARNING_ACTIVATION_THRESHOLD 10 + +enum wsrep_warning_type { + WSREP_DISABLED = 0, + WSREP_REQUIRE_PRIMARY_KEY= 1, + WSREP_REQUIRE_INNODB= 2, + WSREP_REQUIRE_MAX=3, +}; + +static ulonglong wsrep_warning_start_time=0; +static bool wsrep_warning_active[WSREP_REQUIRE_MAX+1]; +static ulonglong wsrep_warning_count[WSREP_REQUIRE_MAX+1]; +static ulonglong wsrep_total_warnings_count=0; + +/** + Auxiliary function to reset the limit of wsrep warnings. + This is done without mutex protection, but this should be good + enough as it doesn't matter if we loose a couple of suppressed + messages or if this is called multiple times. +*/ + +static void wsrep_reset_warnings(ulonglong now) +{ + uint i; + + wsrep_warning_start_time= now; + wsrep_total_warnings_count= 0; + + for (i= 0 ; i < WSREP_REQUIRE_MAX ; i++) + { + wsrep_warning_active[i]= false; + wsrep_warning_count[i]= 0; + } +} + +static const char* wsrep_warning_name(const enum wsrep_warning_type type) +{ + switch(type) + { + case WSREP_REQUIRE_PRIMARY_KEY: + return "WSREP_REQUIRE_PRIMARY_KEY"; break; + case WSREP_REQUIRE_INNODB: + return "WSREP_REQUIRE_INNODB"; break; + default: assert(0); + } +} +/** + Auxiliary function to check if the warning statements should be + thrown or suppressed. + + Logic is: + - If we get more than WSREP_WARNING_ACTIVATION_THRESHOLD errors + of one type, that type of errors will be suppressed for + WSREP_WARNING_ACTIVATION_TIMEOUT. + - When the time limit has been reached, all suppressions are reset. + + This means that if one gets many different types of errors, some of them + may be reset less than WSREP_WARNING_ACTIVATION_TIMEOUT. However at + least one error is disabled for this time. + + SYNOPSIS: + @params + warning_type - The type of warning. + + RETURN: + 0 0k to log + 1 Message suppressed +*/ + +static bool wsrep_protect_against_warning_flood( + enum wsrep_warning_type warning_type) +{ + ulonglong count; + ulonglong now= my_interval_timer()/1000000000ULL; + + count= ++wsrep_warning_count[warning_type]; + wsrep_total_warnings_count++; + + /* + INITIALIZING: + If this is the first time this function is called with log warning + enabled, the monitoring the warnings should start. + */ + if (wsrep_warning_start_time == 0) + { + wsrep_reset_warnings(now); + return false; + } + + /* + The following is true if we got too many errors or if the error was + already suppressed + */ + if (count >= WSREP_WARNING_ACTIVATION_THRESHOLD) + { + ulonglong diff_time= (now - wsrep_warning_start_time); + + if (!wsrep_warning_active[warning_type]) + { + /* + ACTIVATION: + We got WSREP_WARNING_ACTIVATION_THRESHOLD warnings in + less than WSREP_WARNING_ACTIVATION_TIMEOUT we activate the + suppression. + */ + if (diff_time <= WSREP_WARNING_ACTIVATION_TIMEOUT) + { + wsrep_warning_active[warning_type]= true; + WSREP_INFO("Suppressing warnings of type '%s' for up to %d seconds because of flooding", + wsrep_warning_name(warning_type), + WSREP_WARNING_ACTIVATION_TIMEOUT); + } + else + { + /* + There is no flooding till now, therefore we restart the monitoring + */ + wsrep_reset_warnings(now); + } + } + else + { + /* This type of warnings was suppressed */ + if (diff_time > WSREP_WARNING_ACTIVATION_TIMEOUT) + { + ulonglong save_count= wsrep_total_warnings_count; + /* Print a suppression note and remove the suppression */ + wsrep_reset_warnings(now); + WSREP_INFO("Suppressed %lu unsafe warnings during " + "the last %d seconds", + save_count, (int) diff_time); + } + } + } + + return wsrep_warning_active[warning_type]; +} + +/** + Auxiliary function to push warning to client and to the error log +*/ +static void wsrep_push_warning(THD *thd, + enum wsrep_warning_type type, + const handlerton *hton, + const TABLE_LIST *tables) +{ + switch(type) + { + case WSREP_REQUIRE_PRIMARY_KEY: + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_OPTION_PREVENTS_STATEMENT, + "WSREP: wsrep_mode = REQUIRED_PRIMARY_KEY enabled. " + "Table '%s'.'%s' should have PRIMARY KEY defined.", + tables->db.str, tables->table_name.str); + if (global_system_variables.log_warnings > 1 && + !wsrep_protect_against_warning_flood(type)) + WSREP_WARN("wsrep_mode = REQUIRED_PRIMARY_KEY enabled. " + "Table '%s'.'%s' should have PRIMARY KEY defined", + tables->db.str, tables->table_name.str); + break; + case WSREP_REQUIRE_INNODB: + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_OPTION_PREVENTS_STATEMENT, + "WSREP: wsrep_mode = STRICT_REPLICATION enabled. " + "Storage engine %s for table '%s'.'%s' is " + "not supported in Galera", + ha_resolve_storage_engine_name(hton), + tables->db.str, tables->table_name.str); + if (global_system_variables.log_warnings > 1 && + !wsrep_protect_against_warning_flood(type)) + WSREP_WARN("wsrep_mode = STRICT_REPLICATION enabled. " + "Storage engine %s for table '%s'.'%s' is " + "not supported in Galera", + ha_resolve_storage_engine_name(hton), + tables->db.str, tables->table_name.str); + break; + + default: assert(0); break; + } +} + +bool wsrep_check_mode_after_open_table (THD *thd, + const handlerton *hton, + TABLE_LIST *tables) { + enum_sql_command sql_command= thd->lex->sql_command; + bool is_dml_stmt= thd->get_command() != COM_STMT_PREPARE && + (sql_command == SQLCOM_INSERT || + sql_command == SQLCOM_INSERT_SELECT || + sql_command == SQLCOM_REPLACE || + sql_command == SQLCOM_REPLACE_SELECT || + sql_command == SQLCOM_UPDATE || + sql_command == SQLCOM_UPDATE_MULTI || + sql_command == SQLCOM_LOAD || + sql_command == SQLCOM_DELETE); + + if (!is_dml_stmt) + return true; + + const legacy_db_type db_type= hton->db_type; + bool replicate= (wsrep_replicate_myisam && db_type == DB_TYPE_MYISAM); + TABLE *tbl= tables->table; + + if (replicate) + { + /* It is not recommended to replicate MyISAM as it lacks rollback feature + but if user demands then actions are replicated using TOI. + Following code will kick-start the TOI but this has to be done only once + per statement. + Note: kick-start will take-care of creating isolation key for all tables + involved in the list (provided all of them are MYISAM tables). */ + if (!is_stat_table(&tables->db, &tables->alias)) + { + if (tbl->s->primary_key == MAX_KEY && + wsrep_check_mode(WSREP_MODE_REQUIRED_PRIMARY_KEY)) + { + /* Other replicated table doesn't have explicit primary-key defined. */ + wsrep_push_warning(thd, WSREP_REQUIRE_PRIMARY_KEY, hton, tables); + } + + wsrep_before_rollback(thd, true); + wsrep_after_rollback(thd, true); + wsrep_after_statement(thd); + WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (tables)); + } + } else if (db_type != DB_TYPE_UNKNOWN && + db_type != DB_TYPE_PERFORMANCE_SCHEMA) + { + bool is_system_db= (tbl && + ((strcmp(tbl->s->db.str, "mysql") == 0) || + (strcmp(tbl->s->db.str, "information_schema") == 0))); + + if (!is_system_db && + !is_temporary_table(tables)) + { + + if (db_type != DB_TYPE_INNODB && + wsrep_check_mode(WSREP_MODE_STRICT_REPLICATION)) + { + /* Table is not an InnoDB table and strict replication is requested*/ + wsrep_push_warning(thd, WSREP_REQUIRE_INNODB, hton, tables); + } + + if (tbl->s->primary_key == MAX_KEY && + db_type == DB_TYPE_INNODB && + wsrep_check_mode(WSREP_MODE_REQUIRED_PRIMARY_KEY)) + { + /* InnoDB table doesn't have explicit primary-key defined. */ + wsrep_push_warning(thd, WSREP_REQUIRE_PRIMARY_KEY, hton, tables); + } + } + } + + return true; + +wsrep_error_label: + return false; } bool wsrep_check_mode_before_cmd_execute (THD *thd) -{ +{ bool ret= true; - if (wsrep_check_mode(WSREP_MODE_BINLOG_ROW_FORMAT_ONLY) && + if (wsrep_check_mode(WSREP_MODE_BINLOG_ROW_FORMAT_ONLY) && !thd->is_current_stmt_binlog_format_row() && is_update_query(thd->lex->sql_command)) { my_error(ER_GALERA_REPLICATION_NOT_SUPPORTED, MYF(0)); @@ -1186,7 +1445,7 @@ bool wsrep_check_mode_before_cmd_execute (THD *thd) "WSREP: wsrep_mode = BINLOG_ROW_FORMAT_ONLY enabled. Only ROW binlog format is supported."); ret= false; } - if (wsrep_check_mode(WSREP_MODE_REQURIED_PRIMARY_KEY) && + if (wsrep_check_mode(WSREP_MODE_REQUIRED_PRIMARY_KEY) && thd->lex->sql_command == SQLCOM_CREATE_TABLE) { Key *key; diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 87991ce33f5..1aad684bd0a 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -137,7 +137,7 @@ enum enum_wsrep_ignore_apply_error { enum enum_wsrep_mode { WSREP_MODE_STRICT_REPLICATION= (1ULL << 0), WSREP_MODE_BINLOG_ROW_FORMAT_ONLY= (1ULL << 1), - WSREP_MODE_REQURIED_PRIMARY_KEY= (1ULL << 2) + WSREP_MODE_REQUIRED_PRIMARY_KEY= (1ULL << 2) }; // Streaming Replication @@ -217,7 +217,8 @@ extern void wsrep_stop_replication(THD *thd); extern bool wsrep_start_replication(const char *wsrep_cluster_address); extern void wsrep_shutdown_replication(); extern bool wsrep_check_mode (enum_wsrep_mode mask); -extern bool wsrep_check_mode_after_open_table (THD *thd, legacy_db_type db_type); +extern bool wsrep_check_mode_after_open_table (THD *thd, const handlerton *hton, + TABLE_LIST *tables); extern bool wsrep_check_mode_before_cmd_execute (THD *thd); extern bool wsrep_must_sync_wait (THD* thd, uint mask= WSREP_SYNC_WAIT_BEFORE_READ); extern bool wsrep_sync_wait (THD* thd, uint mask= WSREP_SYNC_WAIT_BEFORE_READ); |