Commit 208233be authored by Jan Lindström's avatar Jan Lindström

MDEV-24830 : Write a warning to error log if Galera replicates InnoDB table with no primary key

Two new features for Galera
* Write a warning to error log if Galera replicates table with storage engine not supported by Galera (at the moment only InnoDB is supported
** Warning is pushed to client also
** MyISAM is allowed if wsrep_replicate_myisam=ON
* Write a warning to error log if Galera replicates table with no primary key
** Warning is pushed to client also
** MyISAM is allowed if wsrep_relicate_myisam=ON
* In both cases apply flood control if > 10 same warning is writen to error log
(requires log_warnings > 1), flood control will suppress warnings for 300 seconds
parent 420f8e24
......@@ -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
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]
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]
......@@ -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
#
# 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
#
# 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
......@@ -4431,13 +4431,16 @@ bool open_tables(THD *thd, const DDL_options_st &options,
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 @@ bool open_tables(THD *thd, const DDL_options_st &options,
#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);
......
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment