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)
{
switch(thd->lex->sql_command)
{
// Mask away some security related details from error log
case SQLCOM_CREATE_USER:
return "CREATE USER";
case SQLCOM_GRANT:
......@@ -67,12 +68,10 @@ extern "C" const char *wsrep_thd_query(const THD *thd)
return "REVOKE";
case SQLCOM_SET_OPTION:
if (thd->lex->definer)
return "SET PASSWORD";
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,7 +4873,8 @@ 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(),
lex->table_type == TABLE_TYPE_SEQUENCE);
......@@ -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;
}
......@@ -5983,7 +6008,7 @@ mysql_execute_command(THD *thd)
#ifdef WITH_WSREP
thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK;
WSREP_TO_ISOLATION_END;
/*
Force release of transactional locks if not in active MST and wsrep is on.
......
......@@ -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))
DBUG_RETURN(TRUE);
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))
......
......@@ -5685,12 +5685,20 @@ static Sys_var_enum Sys_wsrep_OSU_method(
static PolyLock_mutex PLock_wsrep_desync(&LOCK_wsrep_desync);
static Sys_var_mybool Sys_wsrep_desync (
"wsrep_desync", "To desynchronize the node from the cluster",
GLOBAL_VAR(wsrep_desync),
GLOBAL_VAR(wsrep_desync),
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
&PLock_wsrep_desync, NOT_IN_BINLOG,
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
......@@ -96,6 +96,9 @@ my_bool wsrep_restart_slave; // Should mysql slave thread be
// restarted, when node joins back?
my_bool wsrep_desync; // De(re)synchronize the node from the
// cluster
my_bool wsrep_strict_ddl; // Reject DDL to
// effected tables not
// supporting Galera replication
long wsrep_slave_threads; // No. of slave appliers threads
ulong wsrep_retry_autocommit; // Retry aborted autocommit trx
ulong wsrep_max_ws_size; // Max allowed ws (RBR buffer) size
......@@ -1296,11 +1299,11 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
}
static bool wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
Alter_info* alter_info,
const Alter_info* alter_info,
wsrep_key_arr_t* ka)
{
Key *key;
List_iterator<Key> key_iterator(alter_info->key_list);
List_iterator<Key> key_iterator(const_cast<Alter_info*>(alter_info)->key_list);
while ((key= key_iterator++))
{
if (key->type == Key::FOREIGN_KEY)
......@@ -1436,12 +1439,12 @@ wsrep::key wsrep_prepare_key_for_toi(const char* db, const char* table,
wsrep::key_array
wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
Alter_info* alter_info)
const Alter_info* alter_info)
{
wsrep::key_array ret;
Key *key;
List_iterator<Key> key_iterator(alter_info->key_list);
List_iterator<Key> key_iterator(const_cast<Alter_info*>(alter_info)->key_list);
while ((key= key_iterator++))
{
if (key->type == Key::FOREIGN_KEY)
......@@ -1463,7 +1466,7 @@ wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
wsrep::key_array wsrep_prepare_keys_for_toi(const char* db,
const char* table,
const TABLE_LIST* table_list,
Alter_info* alter_info)
const Alter_info* alter_info)
{
wsrep::key_array ret;
if (db || table)
......@@ -1735,6 +1738,51 @@ static int wsrep_drop_table_query(THD* thd, uchar** buf, size_t* buf_len)
/* Forward declarations. */
int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
bool wsrep_should_replicate_ddl_iterate(THD* thd, const TABLE_LIST* table_list)
{
if (WSREP(thd))
{
for (const TABLE_LIST* it= table_list; it; it= it->next_global)
{
if (!wsrep_should_replicate_ddl(thd, it->table->s->db_type()->db_type))
return false;
}
}
return true;
}
bool wsrep_should_replicate_ddl(THD* thd,
const enum legacy_db_type db_type)
{
if (!wsrep_strict_ddl)
return true;
switch (db_type)
{
case DB_TYPE_INNODB:
return true;
break;
case DB_TYPE_MYISAM:
if (wsrep_replicate_myisam)
return true;
else
WSREP_DEBUG("wsrep OSU failed for %s", wsrep_thd_query(thd));
break;
case DB_TYPE_ARIA:
/* if (wsrep_replicate_aria) */
/* fallthrough */
default:
WSREP_DEBUG("wsrep OSU failed for %s", wsrep_thd_query(thd));
break;
}
/* STRICT, treat as error */
my_error(ER_GALERA_REPLICATION_NOT_SUPPORTED, MYF(0));
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA,
"WSREP: wsrep_strict_ddl=true and storage engine does not support Galera replication.");
return false;
}
/*
Decide if statement should run in TOI.
......@@ -1745,24 +1793,28 @@ int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
should be rewritten at later time for replication to contain only
non-temporary tables.
*/
static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
const TABLE_LIST *table_list)
bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
const TABLE_LIST *table_list,
const HA_CREATE_INFO* create_info)
{
DBUG_ASSERT(!table || db);
DBUG_ASSERT(table_list || db);
LEX* lex= thd->lex;
SELECT_LEX* select_lex= lex->first_select_lex();
TABLE_LIST* first_table= select_lex->table_list.first;
const TABLE_LIST* first_table= select_lex->table_list.first;
switch (lex->sql_command)
{
case SQLCOM_CREATE_TABLE:
DBUG_ASSERT(!table_list);
if (thd->lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
{
return false;
}
if (!wsrep_should_replicate_ddl(thd, create_info->db_type->db_type))
{
return false;
}
/*
If mariadb master has replicated a CTAS, we should not replicate the create table
part separately as TOI, but to replicate both create table and following inserts
......@@ -1771,7 +1823,8 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
as TOI. We have to do relay log event lookup to see if row events follow the
create table event.
*/
if (thd->slave_thread && !(thd->rgi_slave->gtid_ev_flags2 & Gtid_log_event::FL_STANDALONE))
if (thd->slave_thread &&
!(thd->rgi_slave->gtid_ev_flags2 & Gtid_log_event::FL_STANDALONE))
{
/* this is CTAS, either empty or populated table */
ulonglong event_size = 0;
......@@ -1797,7 +1850,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
}
/* no next async replication event */
return true;
break;
case SQLCOM_CREATE_VIEW:
DBUG_ASSERT(!table_list);
......@@ -1806,7 +1859,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
If any of the remaining tables refer to temporary table error
is returned to client, so TOI can be skipped
*/
for (TABLE_LIST* it= first_table->next_global; it; it= it->next_global)
for (const TABLE_LIST* it= first_table->next_global; it; it= it->next_global)
{
if (thd->find_temporary_table(it))
{
......@@ -1814,7 +1867,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
}
}
return true;
break;
case SQLCOM_CREATE_TRIGGER:
DBUG_ASSERT(first_table);
......@@ -1824,15 +1877,12 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
return false;
}
return true;
case SQLCOM_DROP_TRIGGER:
DBUG_ASSERT(table_list);
if (thd->find_temporary_table(table_list))
{
break;
case SQLCOM_ALTER_TABLE:
if (create_info &&
!wsrep_should_replicate_ddl(thd, create_info->db_type->db_type))
return false;
}
return true;
/* fallthrough */
default:
if (table && !thd->find_temporary_table(db, table))
{
......@@ -1841,7 +1891,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
if (table_list)
{
for (TABLE_LIST* table= first_table; table; table= table->next_global)
for (const TABLE_LIST* table= first_table; table; table= table->next_global)
{
if (!thd->find_temporary_table(table->db.str, table->table_name.str))
{
......@@ -1849,11 +1899,12 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
}
}
}
return !(table || table_list);
break;
}
}
static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
{
String log_query;
......@@ -1962,14 +2013,16 @@ static void wsrep_TOI_begin_failed(THD* thd, const wsrep_buf_t* /* const err */)
*/
static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
const TABLE_LIST* table_list,
Alter_info* alter_info)
const Alter_info* alter_info,
const HA_CREATE_INFO* create_info)
{
DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI);
DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_TOI);
WSREP_DEBUG("TOI Begin: %s", wsrep_thd_query(thd));
WSREP_DEBUG("TOI Begin");
if (wsrep_can_run_in_toi(thd, db, table, table_list) == false)
if (wsrep_can_run_in_toi(thd, db, table, table_list, create_info) == false)
{
WSREP_DEBUG("No TOI for %s", WSREP_QUERY(thd));
WSREP_DEBUG("No TOI for %s", wsrep_thd_query(thd));
return 1;
}
......@@ -1979,6 +2032,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
int rc;
buf_err= wsrep_TOI_event_buf(thd, &buf, &buf_len);
if (buf_err) {
WSREP_ERROR("Failed to create TOI event buf: %d", buf_err);
my_message(ER_UNKNOWN_ERROR,
......@@ -1987,6 +2041,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
MYF(0));
return -1;
}
struct wsrep_buf buff= { buf, buf_len };
wsrep::key_array key_array=
......@@ -1997,7 +2052,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
/* non replicated DDL, affecting temporary tables only */
WSREP_DEBUG("TO isolation skipped, sql: %s."
"Only temporary tables affected.",
WSREP_QUERY(thd));
wsrep_thd_query(thd));
if (buf) my_free(buf);
return -1;
}
......@@ -2005,6 +2060,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
thd_proc_info(thd, "acquiring total order isolation");
wsrep::client_state& cs(thd->wsrep_cs());
int ret= cs.enter_toi_local(key_array,
wsrep::const_buffer(buff.ptr, buff.len));
......@@ -2012,7 +2068,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
{
DBUG_ASSERT(cs.current_error());
WSREP_DEBUG("to_execute_start() failed for %llu: %s, seqno: %lld",
thd->thread_id, WSREP_QUERY(thd),
thd->thread_id, wsrep_thd_query(thd),
(long long)wsrep_thd_trx_seqno(thd));
/* jump to error handler in mysql_execute_command() */
......@@ -2023,7 +2079,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
"Maximum size exceeded.",
ret,
(thd->db.str ? thd->db.str : "(null)"),
WSREP_QUERY(thd));
wsrep_thd_query(thd));
my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED);
break;
default:
......@@ -2031,7 +2087,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
"Check wsrep connection state and retry the query.",
ret,
(thd->db.str ? thd->db.str : "(null)"),
WSREP_QUERY(thd));
wsrep_thd_query(thd));
if (!thd->is_error())
{
my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check "
......@@ -2079,7 +2135,7 @@ static void wsrep_TOI_end(THD *thd) {
wsrep::client_state& client_state(thd->wsrep_cs());
DBUG_ASSERT(wsrep_thd_is_local_toi(thd));
WSREP_DEBUG("TO END: %lld: %s", client_state.toi_meta().seqno().get(),
WSREP_QUERY(thd));
wsrep_thd_query(thd));
wsrep_gtid_server.signal_waiters(thd->wsrep_current_gtid_seqno, false);
......@@ -2104,7 +2160,7 @@ static void wsrep_TOI_end(THD *thd) {
else
{
WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s",
ret, (thd->db.str ? thd->db.str : "(null)"), WSREP_QUERY(thd));
ret, (thd->db.str ? thd->db.str : "(null)"), wsrep_thd_query(thd));
}
}
}
......@@ -2112,7 +2168,7 @@ static void wsrep_TOI_end(THD *thd) {
static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_)
{
WSREP_DEBUG("RSU BEGIN: %lld, : %s", wsrep_thd_trx_seqno(thd),
WSREP_QUERY(thd));
wsrep_thd_query(thd));
if (thd->wsrep_cs().begin_rsu(5000))
{
WSREP_WARN("RSU begin failed");
......@@ -2127,7 +2183,7 @@ static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_)
static void wsrep_RSU_end(THD *thd)
{
WSREP_DEBUG("RSU END: %lld : %s", wsrep_thd_trx_seqno(thd),
WSREP_QUERY(thd));
wsrep_thd_query(thd));
if (thd->wsrep_cs().end_rsu())
{
WSREP_WARN("Failed to end RSU, server may need to be restarted");
......@@ -2137,7 +2193,8 @@ static void wsrep_RSU_end(THD *thd)
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list,
Alter_info* alter_info)
const Alter_info* alter_info,
const HA_CREATE_INFO* create_info)
{
/*
No isolation for applier or replaying threads.
......@@ -2162,14 +2219,14 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
if (thd->global_read_lock.is_acquired())
{
WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %llu",
WSREP_QUERY(thd), thd->thread_id);
wsrep_thd_query(thd), thd->thread_id);
return -1;
}
if (wsrep_debug && thd->mdl_context.has_locks())
{
WSREP_DEBUG("thread holds MDL locks at TI begin: %s %llu",
WSREP_QUERY(thd), thd->thread_id);
wsrep_thd_query(thd), thd->thread_id);
}
/*
......@@ -2187,24 +2244,24 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
if (thd->variables.wsrep_on && wsrep_thd_is_local(thd))
{
switch (thd->variables.wsrep_OSU_method) {
switch (wsrep_OSU_method_get(thd)) {
case WSREP_OSU_TOI:
ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info);
ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info, create_info);
break;
case WSREP_OSU_RSU:
ret= wsrep_RSU_begin(thd, db_, table_);
break;
default:
WSREP_ERROR("Unsupported OSU method: %lu",
thd->variables.wsrep_OSU_method);
wsrep_OSU_method_get(thd));
ret= -1;
break;
}
switch (ret) {
case 0: /* wsrep_TOI_begin sould set toi mode */ break;
case 0: /* wsrep_TOI_begin should set toi mode */ break;
case 1:
/* TOI replication skipped, treat as success */
ret= 0;
/* TOI replication skipped, treat as success */
ret= 0;
break;
case -1:
/* TOI replication failed, treat as error */
......@@ -2221,12 +2278,12 @@ void wsrep_to_isolation_end(THD *thd)
wsrep_thd_is_in_rsu(thd));
if (wsrep_thd_is_local_toi(thd))
{
DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI);
DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_TOI);
wsrep_TOI_end(thd);
}
else if (wsrep_thd_is_in_rsu(thd))
{
DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_RSU);
DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_RSU);
wsrep_RSU_end(thd);
}
else
......@@ -2678,17 +2735,17 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
if (create_info->tmp_table())
{
/* CREATE TEMPORARY TABLE LIKE must be skipped from replication */
WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s",
WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s",
thd->query());
}
else if (!(thd->find_temporary_table(src_table)))
{
/* this is straight CREATE TABLE LIKE... with no tmp tables */
WSREP_TO_ISOLATION_BEGIN(table->db.str, table->table_name.str, NULL);
WSREP_TO_ISOLATION_BEGIN_CREATE(table->db.str, table->table_name.str, table, create_info);
}
else
{
/* here we have CREATE TABLE LIKE <temporary table>
/* here we have CREATE TABLE LIKE <temporary table>
the temporary table definition will be needed in slaves to
enable the create to succeed
*/
......@@ -2707,7 +2764,7 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
thd->wsrep_TOI_pre_query= query.ptr();
thd->wsrep_TOI_pre_query_len= query.length();
WSREP_TO_ISOLATION_BEGIN(table->db.str, table->table_name.str, NULL);
WSREP_TO_ISOLATION_BEGIN_CREATE(table->db.str, table->table_name.str, table, create_info);
thd->wsrep_TOI_pre_query= NULL;
thd->wsrep_TOI_pre_query_len= 0;
......
......@@ -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