Commit e913f4e1 authored by Jan Lindström's avatar Jan Lindström Committed by Julius Goryavsky

MDEV-32024 : Galera library 26.4.16 fails with every server version

Problem was that total order isolation (TOI) is started before
we know sequence implementing storage engine. This led to
situation where table implementing persistent storate
for sequence in case of MyISAM was created on applier causing
errors later in test execution.

Therefore, in both CREATE SEQUENCE and ALTER TABLE to implementing
persistent storage we need to check implementing storage engine
after open_tables and this check must be done in both master
and applier, because if implementing storage engine is MyISAM
it does not support rollback.

Added tests to make sure that if sequence implementing storage
engine is MyISAM or we try to alter it to MyISAM user gets error
and changes are not replicated.
Signed-off-by: default avatarJulius Goryavsky <julius.goryavsky@mariadb.com>
parent 7d89dcf1
connection node_2;
connection node_1;
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_1;
SET DEBUG_SYNC = 'wsrep_create_table_as_select WAIT_FOR continue';
CREATE table t1 as SELECT SLEEP(0.1);;
connection node_1a;
# Wait until CTAS is on debug sync point
connection node_1b;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL debug_dbug = '+d,sync.wsrep_apply_cb';
connection node_2;
CREATE table t1 as SELECT SLEEP(0.2);;
connection node_1b;
SET SESSION debug_sync = 'now WAIT_FOR sync.wsrep_apply_cb_reached';
# Signal first CTAS to continue and wait until CTAS has executed
SET DEBUG_SYNC= 'now SIGNAL continue';
SET GLOBAL debug_dbug= '';
SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb';
connection node_2a;
connection node_1b;
SET DEBUG_SYNC= 'RESET';
connection node_2;
connection node_1;
DROP TABLE t1;
disconnect node_2;
disconnect node_1;
# End of test
......@@ -31,7 +31,7 @@ select NEXT VALUE FOR Seq1_1;
NEXT VALUE FOR Seq1_1
1
alter table Seq1_1 engine=myisam;
ERROR 42000: This version of MariaDB doesn't yet support 'Galera cluster does support only InnoDB sequences'
ERROR 42000: This version of MariaDB doesn't yet support 'non-InnoDB sequences in Galera cluster'
select NEXT VALUE FOR Seq1_1;
NEXT VALUE FOR Seq1_1
2
......@@ -156,7 +156,53 @@ a b
DROP TABLE t1;
DROP SEQUENCE t;
CREATE SEQUENCE t ENGINE=MYISAM;
ERROR 42000: This version of MariaDB doesn't yet support 'Galera cluster does support only InnoDB sequences'
ERROR 42000: This version of MariaDB doesn't yet support 'non-InnoDB sequences in Galera cluster'
SHOW CREATE SEQUENCE t;
ERROR 42S02: Table 'test.t' doesn't exist
SHOW CREATE TABLE t;
ERROR 42S02: Table 'test.t' doesn't exist
connection node_2;
SHOW CREATE SEQUENCE t;
ERROR 42S02: Table 'test.t' doesn't exist
SHOW CREATE TABLE t;
ERROR 42S02: Table 'test.t' doesn't exist
connection node_1;
CREATE SEQUENCE t NOCACHE ENGINE=InnoDB;
ALTER TABLE t ENGINE=MyISAM;
ERROR 42000: This version of MariaDB doesn't yet support 'non-InnoDB sequences in Galera cluster'
SHOW CREATE SEQUENCE t;
Table Create Table
t CREATE SEQUENCE `t` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB
SHOW CREATE TABLE t;
Table Create Table
t CREATE TABLE `t` (
`next_not_cached_value` bigint(21) NOT NULL,
`minimum_value` bigint(21) NOT NULL,
`maximum_value` bigint(21) NOT NULL,
`start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
`increment` bigint(21) NOT NULL COMMENT 'increment value',
`cache_size` bigint(21) unsigned NOT NULL,
`cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
`cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
) ENGINE=InnoDB SEQUENCE=1
connection node_2;
SHOW CREATE SEQUENCE t;
Table Create Table
t CREATE SEQUENCE `t` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB
SHOW CREATE TABLE t;
Table Create Table
t CREATE TABLE `t` (
`next_not_cached_value` bigint(21) NOT NULL,
`minimum_value` bigint(21) NOT NULL,
`maximum_value` bigint(21) NOT NULL,
`start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
`increment` bigint(21) NOT NULL COMMENT 'increment value',
`cache_size` bigint(21) unsigned NOT NULL,
`cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed',
`cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
) ENGINE=InnoDB SEQUENCE=1
connection node_1;
DROP SEQUENCE t;
CREATE SEQUENCE t INCREMENT BY 1 NOCACHE ENGINE=INNODB;
CREATE TABLE t1(a int not null primary key default nextval(t), b int) engine=innodb;
connection node_2;
......@@ -185,7 +231,7 @@ DROP TABLE t1;
CREATE SEQUENCE t INCREMENT BY 0 NOCACHE ENGINE=INNODB;
DROP SEQUENCE t;
CREATE SEQUENCE t INCREMENT BY 1 CACHE=20 ENGINE=INNODB;
ERROR 42000: This version of MariaDB doesn't yet support 'In Galera if you use CACHE you should set INCREMENT BY 0 to behave correctly in a cluster'
ERROR 42000: This version of MariaDB doesn't yet support 'CACHE without INCREMENT BY 0 in Galera cluster'
CREATE SEQUENCE t INCREMENT BY 0 CACHE=20 ENGINE=INNODB;
CREATE TABLE t1(a int not null primary key default nextval(t), b int) engine=innodb;
connection node_2;
......@@ -201,9 +247,9 @@ DROP SEQUENCE t;
DROP TABLE t1;
CREATE SEQUENCE t INCREMENT BY 0 CACHE=20 ENGINE=INNODB;
ALTER TABLE t ENGINE=MYISAM;
ERROR 42000: This version of MariaDB doesn't yet support 'Galera cluster does support only InnoDB sequences'
ERROR 42000: This version of MariaDB doesn't yet support 'non-InnoDB sequences in Galera cluster'
ALTER SEQUENCE t INCREMENT BY 1 CACHE=10;
ERROR 42000: This version of MariaDB doesn't yet support 'In Galera if you use CACHE you should set INCREMENT BY 0 to behave correctly in a cluster'
ERROR 42000: This version of MariaDB doesn't yet support 'CACHE without INCREMENT BY 0 in Galera cluster'
ALTER SEQUENCE t INCREMENT BY 1 NOCACHE;
ALTER SEQUENCE t INCREMENT BY 0 NOCACHE;
ALTER SEQUENCE t INCREMENT BY 0 CACHE=10;
......
--source include/galera_cluster.inc
--source include/big_test.inc
--source include/have_debug_sync.inc
#
# To have real concurrent CTAS this test uses DEBUG_SYNC
#
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--connection node_1
#
# Send CTAS it will block before open_tables call
#
SET DEBUG_SYNC = 'wsrep_create_table_as_select WAIT_FOR continue';
--send CREATE table t1 as SELECT SLEEP(0.1);
--connection node_1a
#
# Wait for CTAS to block
#
--echo # Wait until CTAS is on debug sync point
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: wsrep_create_table_as_select'
--source include/wait_condition.inc
--connection node_1b
#
# Block node_1 applier
#
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL debug_dbug = '+d,sync.wsrep_apply_cb';
#
# Send concurrent CTAS it will block on applier
#
--connection node_2
--send CREATE table t1 as SELECT SLEEP(0.2);
#
# Wait until second CTAS is blocked
#
--connection node_1b
SET SESSION debug_sync = 'now WAIT_FOR sync.wsrep_apply_cb_reached';
--echo # Signal first CTAS to continue and wait until CTAS has executed
SET DEBUG_SYNC= 'now SIGNAL continue';
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Creating table CREATE table t1 as SELECT SLEEP(0.1)'
--source include/wait_condition.inc
#
# Release second CTAS and cleanup
#
SET GLOBAL debug_dbug= '';
SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb';
#
# Wait until second CTAS continues
#
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'debug sync point: now%'
--source include/wait_condition.inc
#
# Wait until second CTAS finishes
#
--connection node_2a
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Creating table CREATE table t1 as SELECT SLEEP(0.2)'
--source include/wait_condition.inc
#
# Cleanup
#
--connection node_1b
SET DEBUG_SYNC= 'RESET';
#
# Verify that at least one is successful
#
--connection node_2
--reap
--connection node_1
--error 0,ER_TABLE_EXISTS_ERROR,ER_QUERY_INTERRUPTED
--reap
DROP TABLE t1;
--write_file $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql
CREATE table t1 as SELECT SLEEP(0.1);
DROP table t1;
CREATE table t1 as SELECT SLEEP(0.1);
DROP table t1;
CREATE table t1 as SELECT SLEEP(0.1);
DROP table t1;
CREATE table t1 as SELECT SLEEP(0.1);
DROP table t1;
CREATE table t1 as SELECT SLEEP(0.1);
DROP table t1;
CREATE table t1 as SELECT SLEEP(0.1);
DROP table t1;
CREATE table t1 as SELECT SLEEP(0.1);
DROP table t1;
CREATE table t1 as SELECT SLEEP(0.1);
DROP table t1;
CREATE table t1 as SELECT SLEEP(0.2);
CREATE table t2 as SELECT SLEEP(0.2);
CREATE table t3 as SELECT SLEEP(0.2);
CREATE table t4 as SELECT SLEEP(0.2);
CREATE table t5 as SELECT SLEEP(0.2);
CREATE table t6 as SELECT SLEEP(0.2);
CREATE table t7 as SELECT SLEEP(0.2);
CREATE table t8 as SELECT SLEEP(0.2);
CREATE table t9 as SELECT SLEEP(0.2);
DROP table t1;
DROP table t2;
DROP table t3;
DROP table t4;
DROP table t5;
DROP table t6;
DROP table t7;
DROP table t8;
DROP table t9;
EOF
let $run=10;
while($run)
{
--error 0,1
exec $MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_1 test \
< $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql & \
$MYSQL --user=root --host=127.0.0.1 --port=$NODE_MYPORT_2 test \
< $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql;
dec $run;
}
--remove_file $MYSQLTEST_VARDIR/tmp/galera_concurrent.sql
--source include/galera_end.inc
--echo # End of test
......
......@@ -134,6 +134,31 @@ DROP SEQUENCE t;
#
--error ER_NOT_SUPPORTED_YET
CREATE SEQUENCE t ENGINE=MYISAM;
--error ER_NO_SUCH_TABLE
SHOW CREATE SEQUENCE t;
--error ER_NO_SUCH_TABLE
SHOW CREATE TABLE t;
--connection node_2
# Verify that above MyISAM sequence does not replicate
--error ER_NO_SUCH_TABLE
SHOW CREATE SEQUENCE t;
--error ER_NO_SUCH_TABLE
SHOW CREATE TABLE t;
--connection node_1
CREATE SEQUENCE t NOCACHE ENGINE=InnoDB;
--error ER_NOT_SUPPORTED_YET
ALTER TABLE t ENGINE=MyISAM;
SHOW CREATE SEQUENCE t;
SHOW CREATE TABLE t;
--connection node_2
SHOW CREATE SEQUENCE t;
SHOW CREATE TABLE t;
--connection node_1
DROP SEQUENCE t;
CREATE SEQUENCE t INCREMENT BY 1 NOCACHE ENGINE=INNODB;
CREATE TABLE t1(a int not null primary key default nextval(t), b int) engine=innodb;
......@@ -164,15 +189,15 @@ SET SESSION wsrep_sync_wait=0;
while ($count)
{
--connection node_1
--error 0,ER_LOCK_WAIT_TIMEOUT
--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK
INSERT INTO t1(b) values (1);
--connection node_2
--error 0,ER_LOCK_WAIT_TIMEOUT
--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK
INSERT INTO t1(b) values (2);
--error 0,ER_LOCK_WAIT_TIMEOUT
--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK
INSERT INTO t1(b) values (2);
--connection node_1
--error 0,ER_LOCK_WAIT_TIMEOUT
--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK
INSERT INTO t1(b) values (1);
--dec $count
}
......@@ -222,15 +247,15 @@ SET SESSION wsrep_sync_wait=0;
while ($count)
{
--connection node_1
--error 0,ER_LOCK_WAIT_TIMEOUT
--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK
INSERT INTO t1(b) values (1),(2),(3),(4),(5),(6),(7),(8),(9);
--connection node_2
--error 0,ER_LOCK_WAIT_TIMEOUT
--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK
INSERT INTO t1(b) values (21),(22),(23),(24),(25),(26),(27),(28),(29);
--error 0,ER_LOCK_WAIT_TIMEOUT
--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK
INSERT INTO t1(b) values (21),(22),(23),(24),(25),(26),(27),(28),(29);
--connection node_1
--error 0,ER_LOCK_WAIT_TIMEOUT
--error 0,ER_LOCK_WAIT_TIMEOUT,ER_LOCK_DEADLOCK
INSERT INTO t1(b) values (1),(2),(3),(4),(5),(6),(7),(8),(9);
--dec $count
}
......
......@@ -470,22 +470,12 @@ bool Sql_cmd_alter_table::execute(THD *thd)
if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
DBUG_RETURN(TRUE); /* purecov: inspected */
#ifdef WITH_WSREP
if (WSREP(thd) &&
(!thd->is_current_stmt_binlog_format_row() ||
!thd->find_temporary_table(first_table)))
{
wsrep::key_array keys;
wsrep_append_fk_parent_table(thd, first_table, &keys);
WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : NULL),
(lex->name.str ? lex->name.str : NULL),
first_table, &alter_info, &keys)
{
WSREP_WARN("ALTER TABLE isolation failure");
DBUG_RETURN(TRUE);
}
/*
It makes sense to set auto_increment_* to defaults in TOI operations.
Must be done before wsrep_TOI_begin() since Query_log_event encapsulating
......@@ -498,6 +488,19 @@ bool Sql_cmd_alter_table::execute(THD *thd)
thd->variables.auto_increment_offset = 1;
thd->variables.auto_increment_increment = 1;
}
wsrep::key_array keys;
wsrep_append_fk_parent_table(thd, first_table, &keys);
WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : NULL),
(lex->name.str ? lex->name.str : NULL),
first_table, &alter_info, &keys)
{
WSREP_WARN("ALTER TABLE isolation failure");
DBUG_RETURN(TRUE);
}
DEBUG_SYNC(thd, "wsrep_alter_table_after_toi");
}
#endif
......
......@@ -5339,12 +5339,15 @@ int mysql_create_table_no_lock(THD *thd, const LEX_CSTRING *db,
@param thd thread handle
@param seq sequence definition
@retval 0 failure
@retval 1 success
@retval false success
@retval true failure
*/
bool wsrep_check_sequence(THD* thd, const sequence_definition *seq)
{
enum legacy_db_type db_type;
DBUG_ASSERT(WSREP(thd));
if (thd->lex->create_info.used_fields & HA_CREATE_USED_ENGINE)
{
db_type= thd->lex->create_info.db_type->db_type;
......@@ -5359,7 +5362,7 @@ bool wsrep_check_sequence(THD* thd, const sequence_definition *seq)
if (db_type != DB_TYPE_INNODB)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"Galera cluster does support only InnoDB sequences");
"non-InnoDB sequences in Galera cluster");
return(true);
}
......@@ -5370,8 +5373,7 @@ bool wsrep_check_sequence(THD* thd, const sequence_definition *seq)
seq->cache)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"In Galera if you use CACHE you should set INCREMENT BY 0"
" to behave correctly in a cluster");
"CACHE without INCREMENT BY 0 in Galera cluster");
return(true);
}
......@@ -9780,6 +9782,15 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
TABLE *table= table_list->table;
bool versioned= table && table->versioned();
#ifdef WITH_WSREP
/*
If this ALTER TABLE is actually SEQUENCE we need to check
if we can support implementing storage engine.
*/
if (WSREP(thd) && table && table->s->sequence &&
wsrep_check_sequence(thd, thd->lex->create_info.seq_create_info))
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
if (versioned)
{
......@@ -11797,6 +11808,8 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
/* Store reference to table in case of LOCK TABLES */
create_info.table= create_table->table;
DEBUG_SYNC(thd, "wsrep_create_table_as_select");
/*
select_create is currently not re-execution friendly and
needs to be created for every execution of a PS/SP.
......@@ -11855,6 +11868,10 @@ bool Sql_cmd_create_table_like::execute(THD *thd)
!create_info.tmp_table()))
{
#ifdef WITH_WSREP
if (thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE &&
wsrep_check_sequence(thd, lex->create_info.seq_create_info))
DBUG_RETURN(true);
WSREP_TO_ISOLATION_BEGIN_ALTER(create_table->db.str, create_table->table_name.str,
first_table, &alter_info, NULL)
{
......
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