mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
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: Julius Goryavsky <julius.goryavsky@mariadb.com>
This commit is contained in:
committed by
Julius Goryavsky
parent
1d0e3d80d8
commit
94e5b43ff5
@@ -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;
|
||||
|
||||
46
mysql-test/suite/galera/r/galera_temporary_sequences.result
Normal file
46
mysql-test/suite/galera/r/galera_temporary_sequences.result
Normal file
@@ -0,0 +1,46 @@
|
||||
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
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SHOW CREATE SEQUENCE sq1;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SHOW CREATE SEQUENCE sq2;
|
||||
--connection node_1
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SHOW CREATE SEQUENCE sq1;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
SHOW CREATE SEQUENCE sq2;
|
||||
--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;
|
||||
|
||||
37
mysql-test/suite/galera/t/galera_temporary_sequences.test
Normal file
37
mysql-test/suite/galera/t/galera_temporary_sequences.test
Normal file
@@ -0,0 +1,37 @@
|
||||
--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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user