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

MDEV-31335 : Create sequence can cause inconsistency

Do not start TOI for CREATE TEMPORARY SEQUENCE because
object is local only and not replicated. Similarly,
avoid starting RSU for TEMPORARY SEQUENCEs. Finally,
we need to run commit hooks for TEMPORARY SEQUENCEs
because CREATE TEMPORARY SEQUENCE does implicit
commit for previous changes that need to be replicated
and committed.
Signed-off-by: default avatarJulius Goryavsky <julius.goryavsky@mariadb.com>
parent 1d0e3d80
......@@ -79,30 +79,31 @@ SET SESSION autocommit=1;
DROP SEQUENCE seq1;
DROP SEQUENCE seq2;
DROP TABLE t2;
connection node_2;
SET SESSION AUTOCOMMIT=0;
SET SESSION wsrep_OSU_method='RSU';
CREATE TABLE t1(c1 VARCHAR(10));
INSERT INTO t1 (c1) VALUES('');
create temporary sequence sq1 NOCACHE engine=innodb;
create sequence sq2 NOCACHE engine=innodb;
COMMIT;
SET SESSION wsrep_OSU_method='TOI';
SHOW CREATE SEQUENCE sq1;
Table Create Table
sq1 CREATE SEQUENCE `sq1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB
SHOW CREATE SEQUENCE sq2;
Table Create Table
sq2 CREATE SEQUENCE `sq2` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB
connection node_2;
connection node_1;
SHOW CREATE SEQUENCE sq1;
ERROR 42S02: Table 'test.sq1' doesn't exist
SHOW CREATE SEQUENCE sq2;
ERROR 42S02: Table 'test.sq2' doesn't exist
connection node_1;
connection node_2;
SET SESSION AUTOCOMMIT=1;
DROP TABLE t1;
DROP SEQUENCE sq1;
DROP SEQUENCE sq2;
SET SESSION wsrep_OSU_method='TOI';
connection node_1;
CREATE TABLE t (f INT) engine=innodb;
LOCK TABLE t WRITE;
CREATE OR REPLACE SEQUENCE t MAXVALUE=13 INCREMENT BY 1 NOCACHE engine=innodb;
......
connection node_2;
connection node_1;
connection node_2;
SET AUTOCOMMIT=0;
SET SESSION wsrep_OSU_method='RSU';
CREATE TABLE t (i int primary key, j int);
CREATE TEMPORARY SEQUENCE seq2 NOCACHE ENGINE=InnoDB;
COMMIT;
SET SESSION wsrep_OSU_method='RSU';
CREATE SEQUENCE seq1 NOCACHE ENGINE=InnoDB;
SET SESSION wsrep_OSU_method='TOI';
DROP TABLE t;
DROP SEQUENCE seq2;
DROP SEQUENCE seq1;
connection node_1;
CREATE TABLE t (i int primary key, j int) ENGINE=InnoDB;
SET AUTOCOMMIT=0;
INSERT INTO t VALUES (3,0);
CREATE TEMPORARY SEQUENCE seq1 NOCACHE ENGINE=InnoDB;
COMMIT;
INSERT INTO t VALUES (4,0);
CREATE SEQUENCE seq2 NOCACHE ENGINE=InnoDB;
commit;
connection node_2;
SELECT * FROM t;
i j
3 0
4 0
SHOW CREATE TABLE seq1;
ERROR 42S02: Table 'test.seq1' doesn't exist
SHOW CREATE TABLE seq2;
Table Create Table
seq2 CREATE TABLE `seq2` (
`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 TABLE t;
DROP SEQUENCE seq1;
DROP SEQUENCE seq2;
......@@ -72,33 +72,33 @@ DROP TABLE t2;
#
# Case2
#
--connection node_2
SET SESSION AUTOCOMMIT=0;
SET SESSION wsrep_OSU_method='RSU';
CREATE TABLE t1(c1 VARCHAR(10));
INSERT INTO t1 (c1) VALUES('');
create temporary sequence sq1 NOCACHE engine=innodb;
create sequence sq2 NOCACHE engine=innodb;
COMMIT;
SET SESSION wsrep_OSU_method='TOI';
SHOW CREATE SEQUENCE sq1;
SHOW CREATE SEQUENCE sq2;
--connection node_2
--connection node_1
--error ER_NO_SUCH_TABLE
SHOW CREATE SEQUENCE sq1;
--error ER_NO_SUCH_TABLE
SHOW CREATE SEQUENCE sq2;
--connection node_1
--connection node_2
SET SESSION AUTOCOMMIT=1;
DROP TABLE t1;
DROP SEQUENCE sq1;
DROP SEQUENCE sq2;
SET SESSION wsrep_OSU_method='TOI';
#
# MDEV-30388 Assertion `!wsrep_has_changes(thd) || (thd->lex->sql_command == SQLCOM_CREATE_TABLE
# && !thd->is_current_stmt_binlog_format_row()) ||
# thd->wsrep_cs().transaction().state() == wsrep::transaction::s_aborted' failed
#
--connection node_1
CREATE TABLE t (f INT) engine=innodb;
LOCK TABLE t WRITE;
CREATE OR REPLACE SEQUENCE t MAXVALUE=13 INCREMENT BY 1 NOCACHE engine=innodb;
......
--source include/galera_cluster.inc
--source include/have_sequence.inc
--connection node_2
SET AUTOCOMMIT=0;
SET SESSION wsrep_OSU_method='RSU';
CREATE TABLE t (i int primary key, j int);
CREATE TEMPORARY SEQUENCE seq2 NOCACHE ENGINE=InnoDB;
COMMIT;
SET SESSION wsrep_OSU_method='RSU';
CREATE SEQUENCE seq1 NOCACHE ENGINE=InnoDB;
SET SESSION wsrep_OSU_method='TOI';
DROP TABLE t;
DROP SEQUENCE seq2;
DROP SEQUENCE seq1;
--connection node_1
CREATE TABLE t (i int primary key, j int) ENGINE=InnoDB;
SET AUTOCOMMIT=0;
INSERT INTO t VALUES (3,0);
CREATE TEMPORARY SEQUENCE seq1 NOCACHE ENGINE=InnoDB;
COMMIT;
INSERT INTO t VALUES (4,0);
CREATE SEQUENCE seq2 NOCACHE ENGINE=InnoDB;
commit;
--connection node_2
SELECT * FROM t;
--error ER_NO_SUCH_TABLE
SHOW CREATE TABLE seq1;
SHOW CREATE TABLE seq2;
--connection node_1
DROP TABLE t;
DROP SEQUENCE seq1;
DROP SEQUENCE seq2;
......@@ -1975,6 +1975,15 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
}
return true;
case SQLCOM_CREATE_SEQUENCE:
/* No TOI for temporary sequences as they are
not replicated */
if (thd->lex->tmp_table())
{
return false;
}
return true;
default:
if (table && !thd->find_temporary_table(db, table))
{
......@@ -2233,6 +2242,14 @@ 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_thd_query(thd));
/* For CREATE TEMPORARY SEQUENCE we do not start RSU because
object is local only and actually CREATE TABLE + INSERT
*/
if (thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE &&
thd->lex->tmp_table())
return 1;
if (thd->wsrep_cs().begin_rsu(5000))
{
WSREP_WARN("RSU begin failed");
......
......@@ -217,13 +217,18 @@ static inline bool wsrep_run_commit_hook(THD* thd, bool all)
mysql_mutex_lock(&thd->LOCK_thd_data);
/* Transaction creating sequence is TOI or RSU,
CREATE [TEMPORARY] SEQUENCE = CREATE + INSERT (initial value)
CREATE SEQUENCE = CREATE + INSERT (initial value)
and replicated using statement based replication, thus
the commit hooks will be skipped */
the commit hooks will be skipped.
For TEMPORARY SEQUENCES commit hooks will be done as
CREATE + INSERT is not replicated and needs to be
committed locally. */
if (ret &&
(thd->wsrep_cs().mode() == wsrep::client_state::m_toi ||
thd->wsrep_cs().mode() == wsrep::client_state::m_rsu) &&
thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE)
thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE &&
!thd->lex->tmp_table())
ret= false;
mysql_mutex_unlock(&thd->LOCK_thd_data);
......
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