Commit e6a50e41 authored by Jan Lindström's avatar Jan Lindström

MDEV-20051: Add new mode to wsrep_OSU_method in which Galera checks storage...

MDEV-20051: Add new mode to wsrep_OSU_method in which Galera checks storage engine of the effected table

Introduced a new wsrep_strict_ddl configuration variable in which
Galera checks storage engine of the effected table. If table is not
InnoDB (only storage engine currently fully supporting Galera
replication) DDL-statement will return error code:

ER_GALERA_REPLICATION_NOT_SUPPORTED
       eng "DDL-statement is forbidden as table storage engine does not support Galera replication"

However, when wsrep_replicate_myisam=ON we allow DDL-statements to
MyISAM tables. If effected table is allowed storage engine Galera
will run normal TOI.

This new setting should be for now set globally on all
nodes in a cluster. When this setting is set following DDL-clauses
accessing tables not supporting Galera replication are refused:

* CREATE TABLE (e.g. CREATE TABLE t1(a int) engine=Aria
* ALTER TABLE
* TRUNCATE TABLE
* CREATE VIEW
* CREATE TRIGGER
* CREATE INDEX
* DROP INDEX
* RENAME TABLE
* DROP TABLE

Statements on PROCEDURE, EVENT, FUNCTION are allowed as effected
tables are known only at execution. Furthermore, USER, ROLE, SERVER,
DATABASE statements are also allowed as they do not really have
effected table.
parent 41541a7c
......@@ -84,6 +84,7 @@ extern struct wsrep_service_st {
my_bool (*wsrep_get_debug_func)();
void (*wsrep_commit_ordered_func)(MYSQL_THD thd);
my_bool (*wsrep_thd_is_applying_func)(const MYSQL_THD thd);
ulong (*wsrep_OSU_method_get_func)(const MYSQL_THD thd);
my_bool (*wsrep_thd_has_ignored_error_func)(const MYSQL_THD thd);
void (*wsrep_thd_set_ignored_error_func)(MYSQL_THD thd, my_bool val);
} *wsrep_service;
......@@ -126,9 +127,9 @@ extern struct wsrep_service_st {
#define wsrep_get_debug() wsrep_service->wsrep_get_debug_func()
#define wsrep_commit_ordered(T) wsrep_service->wsrep_commit_ordered_func(T)
#define wsrep_thd_is_applying(T) wsrep_service->wsrep_thd_is_applying_func(T)
#define wsrep_OSU_method_get(T) wsrep_service->wsrep_OSU_method_get_func(T)
#define wsrep_thd_has_ignored_error(T) wsrep_service->wsrep_thd_has_ignored_error_func(T)
#define wsrep_thd_set_ignored_error(T,V) wsrep_service->wsrep_thd_set_ignored_error_func(T,V)
#else
#define MYSQL_SERVICE_WSREP_STATIC_INCLUDED
......@@ -220,9 +221,8 @@ extern "C" my_bool wsrep_get_debug();
extern "C" void wsrep_commit_ordered(MYSQL_THD thd);
extern "C" my_bool wsrep_thd_is_applying(const MYSQL_THD thd);
extern "C" ulong wsrep_OSU_method_get(const MYSQL_THD thd);
extern "C" my_bool wsrep_thd_has_ignored_error(const MYSQL_THD thd);
extern "C" void wsrep_thd_set_ignored_error(MYSQL_THD thd, my_bool val);
#endif
#endif /* MYSQL_SERVICE_WSREP_INCLUDED */
......@@ -19,18 +19,27 @@
#include <my_config.h>
#ifdef WITH_WSREP
#define IF_WSREP(A,B) A
#define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A)
#define WSREP_MYSQL_DB (char *)"mysql"
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \
if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \
if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \
goto wsrep_error_label;
#define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_) \
if (WSREP(thd) && \
wsrep_to_isolation_begin(thd, db_, table_, \
table_list_, NULL, create_info_)) \
goto wsrep_error_label;
#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) \
#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, create_info_) \
if (WSREP(thd) && wsrep_thd_is_local(thd) && \
wsrep_to_isolation_begin(thd, db_, table_, \
table_list_, alter_info_)) \
table_list_, alter_info_, create_info_)) \
goto wsrep_error_label;
#define WSREP_TO_ISOLATION_END \
......@@ -56,14 +65,12 @@
* (e.g. embedded) */
#define IF_WSREP(A,B) B
//#define DBUG_ASSERT_IF_WSREP(A)
#define WSREP_DEBUG(...)
//#define WSREP_INFO(...)
//#define WSREP_WARN(...)
#define WSREP_ERROR(...)
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) do { } while(0)
#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_)
#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, create_info_)
#define WSREP_TO_ISOLATION_END
#define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_)
#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_)
#define WSREP_SYNC_WAIT(thd_, before_)
#endif /* WITH_WSREP */
......
connection node_2;
connection node_1;
call mtr.add_suppression("WSREP: ALTER TABLE isolation failure");
connection node_1;
SET GLOBAL binlog_format='ROW';
create table before_t1(a int, count int, b int, key(b)) engine=Aria;
INSERT INTO before_t1 values (1,1,1);
set @@global.wsrep_strict_ddl=ON;
select @@global.wsrep_strict_ddl;
@@global.wsrep_strict_ddl
1
connection node_2;
set @@global.wsrep_strict_ddl=ON;
select @@global.wsrep_strict_ddl;
@@global.wsrep_strict_ddl
1
connection node_1;
CREATE TABLE t1(a int) engine=Aria;
ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
SHOW WARNINGS;
Level Code Message
Error 4165 DDL-statement is forbidden as table storage engine does not support Galera replication
Warning 1031 WSREP: wsrep_strict_ddl=true and storage engine does not support Galera replication.
connection node_2;
SHOW CREATE TABLE t1;
ERROR 42S02: Table 'test.t1' doesn't exist
connection node_1;
CREATE TABLE t2(a int not null primary key) engine=InnoDB;
ALTER TABLE t2 engine=MyISAM;
ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
SHOW WARNINGS;
Level Code Message
Error 4165 DDL-statement is forbidden as table storage engine does not support Galera replication
Warning 1031 WSREP: wsrep_strict_ddl=true and storage engine does not support Galera replication.
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` int(11) NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
connection node_2;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` int(11) NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
connection node_1;
TRUNCATE TABLE before_t1;
ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
SELECT * FROM before_t1;
a count b
1 1 1
connection node_2;
SET SESSION wsrep_sync_wait=15;
SELECT @@wsrep_sync_wait;
@@wsrep_sync_wait
15
SELECT * FROM before_t1;
a count b
connection node_1;
CREATE VIEW x1 AS SELECT * FROM before_t1;
ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
SHOW CREATE VIEW x1;
ERROR 42S02: Table 'test.x1' doesn't exist
connection node_2;
SHOW CREATE VIEW x1;
ERROR 42S02: Table 'test.x1' doesn't exist
connection node_1;
CREATE DEFINER=`root`@`localhost` TRIGGER increment_before_t1
AFTER INSERT ON before_t1 FOR EACH ROW
UPDATE before_t1 SET before_t1.count = before_t1.count+1;
ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
SHOW CREATE TRIGGER increment_before_t1;
ERROR HY000: Trigger does not exist
connection node_2;
SHOW CREATE TRIGGER increment_before_t1;
ERROR HY000: Trigger does not exist
connection node_1;
CREATE INDEX xx2 ON before_t1(a);
ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
SHOW CREATE TABLE before_t1;
Table Create Table
before_t1 CREATE TABLE `before_t1` (
`a` int(11) DEFAULT NULL,
`count` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
connection node_2;
SHOW CREATE TABLE before_t1;
Table Create Table
before_t1 CREATE TABLE `before_t1` (
`a` int(11) DEFAULT NULL,
`count` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
connection node_1;
DROP INDEX b ON before_t1;
ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
SHOW CREATE TABLE before_t1;
Table Create Table
before_t1 CREATE TABLE `before_t1` (
`a` int(11) DEFAULT NULL,
`count` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
connection node_2;
SHOW CREATE TABLE before_t1;
Table Create Table
before_t1 CREATE TABLE `before_t1` (
`a` int(11) DEFAULT NULL,
`count` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
connection node_1;
ALTER TABLE before_t1 ADD COLUMN f int;
ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
SHOW CREATE TABLE before_t1;
Table Create Table
before_t1 CREATE TABLE `before_t1` (
`a` int(11) DEFAULT NULL,
`count` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
connection node_2;
SHOW CREATE TABLE before_t1;
Table Create Table
before_t1 CREATE TABLE `before_t1` (
`a` int(11) DEFAULT NULL,
`count` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
connection node_1;
RENAME TABLE before_t1 to after_t1;
ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
SHOW CREATE TABLE before_t1;
Table Create Table
before_t1 CREATE TABLE `before_t1` (
`a` int(11) DEFAULT NULL,
`count` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
SHOW CREATE TABLE after_t1;
ERROR 42S02: Table 'test.after_t1' doesn't exist
connection node_2;
SHOW CREATE TABLE before_t1;
Table Create Table
before_t1 CREATE TABLE `before_t1` (
`a` int(11) DEFAULT NULL,
`count` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
SHOW CREATE TABLE after_t1;
ERROR 42S02: Table 'test.after_t1' doesn't exist
connection node_1;
DROP TABLE before_t1;
ERROR HY000: DDL-statement is forbidden as table storage engine does not support Galera replication
SHOW CREATE TABLE before_t1;
Table Create Table
before_t1 CREATE TABLE `before_t1` (
`a` int(11) DEFAULT NULL,
`count` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
connection node_2;
SHOW CREATE TABLE before_t1;
Table Create Table
before_t1 CREATE TABLE `before_t1` (
`a` int(11) DEFAULT NULL,
`count` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
connection node_1;
set @@global.wsrep_strict_ddl=OFF;
select @@global.wsrep_strict_ddl;
@@global.wsrep_strict_ddl
0
connection node_2;
set @@global.wsrep_strict_ddl=OFF;
select @@global.wsrep_strict_ddl;
@@global.wsrep_strict_ddl
0
DROP TABLE t2;
DROP TABLE before_t1;
--source include/galera_cluster.inc
call mtr.add_suppression("WSREP: ALTER TABLE isolation failure");
--connection node_1
SET GLOBAL binlog_format='ROW';
create table before_t1(a int, count int, b int, key(b)) engine=Aria;
INSERT INTO before_t1 values (1,1,1);
set @@global.wsrep_strict_ddl=ON;
select @@global.wsrep_strict_ddl;
--connection node_2
set @@global.wsrep_strict_ddl=ON;
select @@global.wsrep_strict_ddl;
--connection node_1
--error ER_GALERA_REPLICATION_NOT_SUPPORTED
CREATE TABLE t1(a int) engine=Aria;
SHOW WARNINGS;
--connection node_2
--error ER_NO_SUCH_TABLE
SHOW CREATE TABLE t1;
--connection node_1
CREATE TABLE t2(a int not null primary key) engine=InnoDB;
--error ER_GALERA_REPLICATION_NOT_SUPPORTED
ALTER TABLE t2 engine=MyISAM;
SHOW WARNINGS;
SHOW CREATE TABLE t2;
--connection node_2
SHOW CREATE TABLE t2;
--connection node_1
--error ER_GALERA_REPLICATION_NOT_SUPPORTED
TRUNCATE TABLE before_t1;
SELECT * FROM before_t1;
--connection node_2
SET SESSION wsrep_sync_wait=15;
SELECT @@wsrep_sync_wait;
SELECT * FROM before_t1;
--connection node_1
--error ER_GALERA_REPLICATION_NOT_SUPPORTED
CREATE VIEW x1 AS SELECT * FROM before_t1;
--error ER_NO_SUCH_TABLE
SHOW CREATE VIEW x1;
--connection node_2
--error ER_NO_SUCH_TABLE
SHOW CREATE VIEW x1;
--connection node_1
--error ER_GALERA_REPLICATION_NOT_SUPPORTED
CREATE DEFINER=`root`@`localhost` TRIGGER increment_before_t1
AFTER INSERT ON before_t1 FOR EACH ROW
UPDATE before_t1 SET before_t1.count = before_t1.count+1;
--error ER_TRG_DOES_NOT_EXIST
SHOW CREATE TRIGGER increment_before_t1;
--connection node_2
--error ER_TRG_DOES_NOT_EXIST
SHOW CREATE TRIGGER increment_before_t1;
--connection node_1
--error ER_GALERA_REPLICATION_NOT_SUPPORTED
CREATE INDEX xx2 ON before_t1(a);
SHOW CREATE TABLE before_t1;
--connection node_2
SHOW CREATE TABLE before_t1;
--connection node_1
--error ER_GALERA_REPLICATION_NOT_SUPPORTED
DROP INDEX b ON before_t1;
SHOW CREATE TABLE before_t1;
--connection node_2
SHOW CREATE TABLE before_t1;
--connection node_1
--error ER_GALERA_REPLICATION_NOT_SUPPORTED
ALTER TABLE before_t1 ADD COLUMN f int;
SHOW CREATE TABLE before_t1;
--connection node_2
SHOW CREATE TABLE before_t1;
--connection node_1
--error ER_GALERA_REPLICATION_NOT_SUPPORTED
RENAME TABLE before_t1 to after_t1;
SHOW CREATE TABLE before_t1;
--error ER_NO_SUCH_TABLE
SHOW CREATE TABLE after_t1;
--connection node_2
SHOW CREATE TABLE before_t1;
--error ER_NO_SUCH_TABLE
SHOW CREATE TABLE after_t1;
--connection node_1
--error ER_GALERA_REPLICATION_NOT_SUPPORTED
DROP TABLE before_t1;
SHOW CREATE TABLE before_t1;
--connection node_2
SHOW CREATE TABLE before_t1;
#
# PROCEDURE, EVENT, FUNCTION
# Unfortunately accessed tables are opened only
# in SP execution so no hope at CREATE
#
# USER, ROLE, SERVER, DATABASE not really storage engine objects
#
--connection node_1
set @@global.wsrep_strict_ddl=OFF;
select @@global.wsrep_strict_ddl;
--connectIon node_2
set @@global.wsrep_strict_ddl=OFF;
select @@global.wsrep_strict_ddl;
DROP TABLE t2;
DROP TABLE before_t1;
......@@ -706,6 +706,21 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
GLOBAL_VALUE_PATH NULL
VARIABLE_NAME WSREP_STRICT_DDL
SESSION_VALUE NULL
GLOBAL_VALUE OFF
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Reject DDL on effected tables not supporting Galera replication
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
GLOBAL_VALUE_PATH NULL
VARIABLE_NAME WSREP_SYNC_WAIT
SESSION_VALUE 0
GLOBAL_VALUE 0
......
#
# wsrep_strict_ddl
#
# save the initial value
SET @wsrep_strict_ddl_global_saved = @@global.wsrep_strict_ddl;
# default
SELECT @@global.wsrep_strict_ddl;
@@global.wsrep_strict_ddl
0
# scope
SELECT @@session.wsrep_strict_ddl;
ERROR HY000: Variable 'wsrep_strict_ddl' is a GLOBAL variable
SET @@global.wsrep_strict_ddl=OFF;
SELECT @@global.wsrep_strict_ddl;
@@global.wsrep_strict_ddl
0
SET @@global.wsrep_strict_ddl=ON;
SELECT @@global.wsrep_strict_ddl;
@@global.wsrep_strict_ddl
1
# valid values
SET @@global.wsrep_strict_ddl='OFF';
SELECT @@global.wsrep_strict_ddl;
@@global.wsrep_strict_ddl
0
SET @@global.wsrep_strict_ddl=ON;
SELECT @@global.wsrep_strict_ddl;
@@global.wsrep_strict_ddl
1
SET @@global.wsrep_strict_ddl=default;
SELECT @@global.wsrep_strict_ddl;
@@global.wsrep_strict_ddl
0
# invalid values
SET @@global.wsrep_strict_ddl=NULL;
ERROR 42000: Variable 'wsrep_strict_ddl' can't be set to the value of 'NULL'
SET @@global.wsrep_strict_ddl='junk';
ERROR 42000: Variable 'wsrep_strict_ddl' can't be set to the value of 'junk'
# restore the initial value
SET @@global.wsrep_strict_ddl = @wsrep_strict_ddl_global_saved;
# End of test
--source include/have_wsrep.inc
--echo #
--echo # wsrep_strict_ddl
--echo #
--echo # save the initial value
SET @wsrep_strict_ddl_global_saved = @@global.wsrep_strict_ddl;
--echo # default
SELECT @@global.wsrep_strict_ddl;
--echo
--echo # scope
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT @@session.wsrep_strict_ddl;
SET @@global.wsrep_strict_ddl=OFF;
SELECT @@global.wsrep_strict_ddl;
SET @@global.wsrep_strict_ddl=ON;
SELECT @@global.wsrep_strict_ddl;
--echo
--echo # valid values
SET @@global.wsrep_strict_ddl='OFF';
SELECT @@global.wsrep_strict_ddl;
SET @@global.wsrep_strict_ddl=ON;
SELECT @@global.wsrep_strict_ddl;
SET @@global.wsrep_strict_ddl=default;
SELECT @@global.wsrep_strict_ddl;
--echo
--echo # invalid values
--error ER_WRONG_VALUE_FOR_VAR
SET @@global.wsrep_strict_ddl=NULL;
--error ER_WRONG_VALUE_FOR_VAR
SET @@global.wsrep_strict_ddl='junk';
--echo
--echo # restore the initial value
SET @@global.wsrep_strict_ddl = @wsrep_strict_ddl_global_saved;
--echo # End of test
......@@ -52,13 +52,14 @@ extern "C" const char* wsrep_thd_transaction_state_str(const THD *thd)
return wsrep::to_c_string(thd->wsrep_cs().transaction().state());
}
extern "C" const char *wsrep_thd_query(const THD *thd)
{
if (thd)
{
if (!thd)
return "NULL";
switch(thd->lex->sql_command)
{
// Mask away some security related details from error log
case SQLCOM_CREATE_USER:
return "CREATE USER";
case SQLCOM_GRANT:
......@@ -70,9 +71,7 @@ extern "C" const char *wsrep_thd_query(const THD *thd)
return "SET PASSWORD";
/* fallthrough */
default:
if (thd->query())
return thd->query();
}
return (thd->query() ? thd->query() : "NULL");
}
return "NULL";
}
......@@ -321,3 +320,11 @@ extern "C" void wsrep_thd_set_ignored_error(THD *thd, my_bool val)
{
thd->wsrep_has_ignored_error= val;
}
extern "C" ulong wsrep_OSU_method_get(const MYSQL_THD thd)
{
if (thd)
return(thd->variables.wsrep_OSU_method);
else
return(global_system_variables.wsrep_OSU_method);
}
......@@ -7943,3 +7943,5 @@ ER_WARN_HISTORY_ROW_START_TIME
eng "Table `%s.%s` history row start '%s' is later than row end '%s'"
ER_PART_STARTS_BEYOND_INTERVAL
eng "%`s: STARTS is later than query time, first history partition may exceed INTERVAL value"
ER_GALERA_REPLICATION_NOT_SUPPORTED
eng "DDL-statement is forbidden as table storage engine does not support Galera replication"
\ No newline at end of file
......@@ -505,9 +505,9 @@ bool Sql_cmd_alter_table::execute(THD *thd)
(!thd->is_current_stmt_binlog_format_row() ||
!thd->find_temporary_table(first_table)))
{
WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : NULL),
(lex->name.str ? lex->name.str : NULL),
first_table, &alter_info);
WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : first_table->db.str),
(lex->name.str ? lex->name.str : first_table->table_name.str),
first_table, &alter_info, used_engine ? &create_info : NULL);
thd->variables.auto_increment_offset = 1;
thd->variables.auto_increment_increment = 1;
......
......@@ -3079,6 +3079,7 @@ mysql_create_routine(THD *thd, LEX *lex)
return true;
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (!lex->sphead->m_handler->sp_create_routine(thd, lex->sphead))
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
......@@ -4147,7 +4148,6 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL);
bzero((char*) &create_info, sizeof(create_info));
create_info.db_type= 0;
......@@ -4155,6 +4155,8 @@ mysql_execute_command(THD *thd)
create_info.default_table_charset= thd->variables.collation_database;
create_info.alter_info= &alter_info;
WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL);
res= mysql_alter_table(thd, &first_table->db, &first_table->table_name,
&create_info, first_table, &alter_info,
0, (ORDER*) 0, 0);
......@@ -4857,6 +4859,7 @@ mysql_execute_command(THD *thd)
slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT)
lex->create_info.set(DDL_options_st::OPT_IF_EXISTS);
#ifdef WITH_WSREP
if (WSREP(thd))
{
for (TABLE_LIST *table= all_tables; table; table= table->next_global)
......@@ -4870,6 +4873,7 @@ mysql_execute_command(THD *thd)
}
}
}
#endif /* WITH_WSREP */
/* DDL and binlog write order are protected by metadata locks. */
res= mysql_rm_table(thd, first_table, lex->if_exists(), lex->tmp_table(),
......@@ -5070,7 +5074,9 @@ mysql_execute_command(THD *thd)
(CREATE_ACL | DROP_ACL) : CREATE_ACL,
&lex->name))
break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL);
res= mysql_create_db(thd, &lex->name,
lex->create_info, &lex->create_info);
break;
......@@ -5079,7 +5085,9 @@ mysql_execute_command(THD *thd)
{
if (prepare_db_action(thd, DROP_ACL, &lex->name))
break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL);
res= mysql_rm_db(thd, &lex->name, lex->if_exists());
break;
}
......@@ -5111,7 +5119,9 @@ mysql_execute_command(THD *thd)
res= 1;
break;
}
WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL);
res= mysql_upgrade_db(thd, db);
if (!res)
my_ok(thd);
......@@ -5122,7 +5132,9 @@ mysql_execute_command(THD *thd)
LEX_CSTRING *db= &lex->name;
if (prepare_db_action(thd, ALTER_ACL, db))
break;
WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL);
res= mysql_alter_db(thd, db, &lex->create_info);
break;
}
......@@ -5196,6 +5208,7 @@ mysql_execute_command(THD *thd)
break;
#ifdef HAVE_DLOPEN
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (!(res = mysql_create_function(thd, &lex->udf)))
my_ok(thd);
#else
......@@ -5213,7 +5226,9 @@ mysql_execute_command(THD *thd)
"mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
if (!(res= mysql_create_user(thd, lex->users_list,
lex->sql_command == SQLCOM_CREATE_ROLE)))
......@@ -5226,8 +5241,10 @@ mysql_execute_command(THD *thd)
if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
if (!(res= mysql_drop_user(thd, lex->users_list,
lex->sql_command == SQLCOM_DROP_ROLE)))
my_ok(thd);
......@@ -5239,8 +5256,10 @@ mysql_execute_command(THD *thd)
if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
if (lex->sql_command == SQLCOM_ALTER_USER)
res= mysql_alter_user(thd, lex->users_list);
else
......@@ -5255,16 +5274,19 @@ mysql_execute_command(THD *thd)
check_global_access(thd,CREATE_USER_ACL))
break;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
if (!(res = mysql_revoke_all(thd, lex->users_list)))
my_ok(thd);
break;
}
case SQLCOM_REVOKE_ROLE:
case SQLCOM_GRANT_ROLE:
{
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (!(res= mysql_grant_role(thd, lex->users_list,
lex->sql_command != SQLCOM_GRANT_ROLE)))
my_ok(thd);
......@@ -5611,6 +5633,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_DROP_PACKAGE:
case SQLCOM_DROP_PACKAGE_BODY:
if (drop_routine(thd, lex))
goto error;
break;
case SQLCOM_SHOW_CREATE_PROC:
......@@ -5676,8 +5699,10 @@ mysql_execute_command(THD *thd)
{
if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE))
goto error;
/* Conditionally writes to binlog. */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog. */
res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
break;
}
......
......@@ -175,6 +175,7 @@ static struct wsrep_service_st wsrep_handler = {
wsrep_get_debug,
wsrep_commit_ordered,
wsrep_thd_is_applying,
wsrep_OSU_method_get,
wsrep_thd_has_ignored_error,
wsrep_thd_set_ignored_error
};
......
......@@ -286,6 +286,13 @@ do_rename(THD *thd, TABLE_LIST *ren_table, const LEX_CSTRING *new_db,
if (ha_table_exists(thd, &ren_table->db, &old_alias, &hton) && hton)
{
DBUG_ASSERT(!thd->locked_tables_mode);
#ifdef WITH_WSREP
if (WSREP(thd) && hton &&
!wsrep_should_replicate_ddl(thd, hton->db_type))
DBUG_RETURN(1);
#endif
tdc_remove_table(thd, TDC_RT_REMOVE_ALL,
ren_table->db.str, ren_table->table_name.str);
......
......@@ -2443,6 +2443,16 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
{
char *end;
int frm_delete_error= 0;
#ifdef WITH_WSREP
if (WSREP(thd) &&
!wsrep_should_replicate_ddl(thd, table_type->db_type))
{
error= 1;
goto err;
}
#endif
/*
It could happen that table's share in the table definition cache
is the only thing that keeps the engine plugin loaded
......@@ -9461,6 +9471,17 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
&alter_prelocking_strategy);
thd->open_options&= ~HA_OPEN_FOR_ALTER;
#ifdef WITH_WSREP
if (WSREP(thd) &&
(thd->lex->sql_command == SQLCOM_ALTER_TABLE ||
thd->lex->sql_command == SQLCOM_CREATE_INDEX ||
thd->lex->sql_command == SQLCOM_DROP_INDEX) &&
!wsrep_should_replicate_ddl(thd, table_list->table->s->db_type()->db_type))
DBUG_RETURN(true);
#endif
DEBUG_SYNC(thd, "alter_table_after_open_tables");
TABLE *table= table_list->table;
bool versioned= table && table->versioned();
......@@ -11503,7 +11524,8 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
(!thd->is_current_stmt_binlog_format_row() ||
!create_info.tmp_table()))
{
WSREP_TO_ISOLATION_BEGIN(create_table->db.str, create_table->table_name.str, NULL);
WSREP_TO_ISOLATION_BEGIN_CREATE(create_table->db.str, create_table->table_name.str,
create_table, &create_info);
}
/* Regular CREATE TABLE */
res= mysql_create_table(thd, create_table, &create_info, &alter_info);
......
......@@ -507,9 +507,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
goto end;
}
#ifdef WITH_WSREP
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, tables);
#endif
/* We should have only one table in table list. */
DBUG_ASSERT(tables->next_global == 0);
......@@ -550,6 +548,12 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
}
table= tables->table;
#ifdef WITH_WSREP
if (WSREP(thd) &&
!wsrep_should_replicate_ddl(thd, table->s->db_type()->db_type))
goto wsrep_error_label;
#endif
/* Later on we will need it to downgrade the lock */
mdl_ticket= table->mdl_ticket;
......
......@@ -303,6 +303,12 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref,
versioned= table->versioned();
hton= table->file->ht;
#ifdef WITH_WSREP
if (WSREP(thd) &&
!wsrep_should_replicate_ddl(thd, hton->db_type))
DBUG_RETURN(TRUE);
#endif
table_ref->mdl_request.ticket= table->mdl_ticket;
}
else
......@@ -320,6 +326,15 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref,
versioned= share->versioned;
sequence= share->table_type == TABLE_TYPE_SEQUENCE;
hton= share->db_type();
#ifdef WITH_WSREP
if (WSREP(thd) &&
hton != view_pseudo_hton &&
!wsrep_should_replicate_ddl(thd, hton->db_type))
{
tdc_release_share(share);
DBUG_RETURN(TRUE);
}
#endif
tdc_release_share(share);
......@@ -417,9 +432,10 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
#ifdef WITH_WSREP
if (WSREP(thd) &&
wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, 0))
wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, NULL))
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
if (lock_table(thd, table_ref, &hton_can_recreate))
DBUG_RETURN(TRUE);
......
......@@ -37,6 +37,7 @@
#include "sql_derived.h"
#include "sql_cte.h" // check_dependencies_in_with_clauses()
#include "opt_trace.h"
#include "wsrep_mysqld.h"
#define MD5_BUFF_LENGTH 33
......@@ -454,6 +455,14 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
goto err;
}
#ifdef WITH_WSREP
if(!wsrep_should_replicate_ddl_iterate(thd, static_cast<const TABLE_LIST *>(tables)))
{
res= TRUE;
goto err;
}
#endif
view= lex->unlink_first_table(&link_to_local);
if (check_db_dir_existence(view->db.str))
......
......@@ -5691,6 +5691,14 @@ static Sys_var_mybool Sys_wsrep_desync (
ON_CHECK(wsrep_desync_check),
ON_UPDATE(wsrep_desync_update));
static Sys_var_mybool Sys_wsrep_strict_ddl (
"wsrep_strict_ddl", "Reject DDL on effected tables not supporting Galera replication",
GLOBAL_VAR(wsrep_strict_ddl),
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(0),
ON_UPDATE(0));
static const char *wsrep_reject_queries_names[]= { "NONE", "ALL", "ALL_KILL", NullS };
static Sys_var_enum Sys_wsrep_reject_queries(
"wsrep_reject_queries", "Variable to set to reject queries",
......
......@@ -144,3 +144,5 @@ my_bool wsrep_thd_has_ignored_error(const THD*)
void wsrep_thd_set_ignored_error(THD*, my_bool)
{ }
ulong wsrep_OSU_method_get(const THD*)
{ return 0;}
\ No newline at end of file
This diff is collapsed.
......@@ -98,6 +98,7 @@ extern ulong wsrep_running_applier_threads;
extern ulong wsrep_running_rollbacker_threads;
extern bool wsrep_new_cluster;
extern bool wsrep_gtid_mode;
extern my_bool wsrep_strict_ddl;
enum enum_wsrep_reject_types {
WSREP_REJECT_NONE, /* nothing rejected */
......@@ -108,7 +109,7 @@ enum enum_wsrep_reject_types {
enum enum_wsrep_OSU_method {
WSREP_OSU_TOI,
WSREP_OSU_RSU,
WSREP_OSU_NONE,
WSREP_OSU_NONE
};
enum enum_wsrep_sync_wait {
......@@ -360,9 +361,15 @@ extern PSI_thread_key key_wsrep_sst_donor_monitor;
struct TABLE_LIST;
class Alter_info;
struct HA_CREATE_INFO;
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list,
Alter_info* alter_info= NULL);
const Alter_info* alter_info= NULL,
const HA_CREATE_INFO* create_info= NULL);
bool wsrep_should_replicate_ddl(THD* thd, const enum legacy_db_type db_type);
bool wsrep_should_replicate_ddl_iterate(THD* thd, const TABLE_LIST* table_list);
void wsrep_to_isolation_end(THD *thd);
......
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