From 5a6de6f40c8ca955d9c0b5159d8ea3afdca626ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 5 Jan 2022 11:52:33 +0200 Subject: MDEV-18848 : Galera: 10.4 node crashed with Assertion `client_state.transaction().active()` after altering SEQUENCE table's engine to myisam and back to innodb We need to start Galera transaction for select NEXT VALUE FOR sequence if it is not yet started. Note that ALTER is handled as TOI and transaction is already started. --- mysql-test/suite/galera/r/galera_sequences.result | 22 ++++++++++++++++++++++ mysql-test/suite/galera/t/galera_sequences.test | 22 ++++++++++++++++++++++ sql/ha_sequence.cc | 17 +++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_sequences.result b/mysql-test/suite/galera/r/galera_sequences.result index e7edc905094..48593d2a258 100644 --- a/mysql-test/suite/galera/r/galera_sequences.result +++ b/mysql-test/suite/galera/r/galera_sequences.result @@ -25,3 +25,25 @@ ERROR 42S02: Table 'test.seq' doesn't exist connection node_2; SHOW CREATE SEQUENCE seq; ERROR 42S02: Table 'test.seq' doesn't exist +connection node_1; +CREATE SEQUENCE Seq1_1 START WITH 1 INCREMENT BY 1; +select NEXT VALUE FOR Seq1_1; +NEXT VALUE FOR Seq1_1 +1 +alter table Seq1_1 engine=myisam; +select NEXT VALUE FOR Seq1_1; +NEXT VALUE FOR Seq1_1 +1001 +alter table Seq1_1 engine=innodb; +select NEXT VALUE FOR Seq1_1; +NEXT VALUE FOR Seq1_1 +2001 +connection node_2; +SHOW CREATE SEQUENCE Seq1_1; +Table Create Table +Seq1_1 CREATE SEQUENCE `Seq1_1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB +select NEXT VALUE FOR Seq1_1; +NEXT VALUE FOR Seq1_1 +1 +connection node_1; +DROP SEQUENCE Seq1_1; diff --git a/mysql-test/suite/galera/t/galera_sequences.test b/mysql-test/suite/galera/t/galera_sequences.test index e2ecdff49d0..480366f6a6f 100644 --- a/mysql-test/suite/galera/t/galera_sequences.test +++ b/mysql-test/suite/galera/t/galera_sequences.test @@ -1,5 +1,9 @@ --source include/galera_cluster.inc +# +# MDEV-19353 : Alter Sequence do not replicate to another nodes with in Galera Cluster +# + --connection node_1 CREATE SEQUENCE `seq` start with 1 minvalue 1 maxvalue 1000000 increment by 0 cache 1000 nocycle ENGINE=InnoDB; SHOW CREATE SEQUENCE seq; @@ -22,3 +26,21 @@ SHOW CREATE SEQUENCE seq; --connection node_2 --error ER_NO_SUCH_TABLE SHOW CREATE SEQUENCE seq; + +# +# MDEV-18848 : Galera: 10.4 node crashed with Assertion `client_state.transaction().active()` after altering SEQUENCE table's engine to myisam and back to innodb +# +--connection node_1 +CREATE SEQUENCE Seq1_1 START WITH 1 INCREMENT BY 1; +select NEXT VALUE FOR Seq1_1; +alter table Seq1_1 engine=myisam; +select NEXT VALUE FOR Seq1_1; +alter table Seq1_1 engine=innodb; +select NEXT VALUE FOR Seq1_1; + +--connection node_2 +SHOW CREATE SEQUENCE Seq1_1; +select NEXT VALUE FOR Seq1_1; + +--connection node_1 +DROP SEQUENCE Seq1_1; diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index 260f2c202fa..b0611c1505a 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -30,6 +30,10 @@ #include "sql_base.h" #include "log_event.h" +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" /* wsrep_start_transaction() */ +#endif + /* Table flags we should inherit and disable from the original engine. We add HA_STATS_RECORDS_IS_EXACT as ha_sequence::info() will ensure @@ -199,6 +203,7 @@ int ha_sequence::write_row(const uchar *buf) int error; sequence_definition tmp_seq; bool sequence_locked; + THD *thd= table->in_use; DBUG_ENTER("ha_sequence::write_row"); DBUG_ASSERT(table->record[0] == buf); @@ -235,8 +240,6 @@ int ha_sequence::write_row(const uchar *buf) on master and slaves - Check that the new row is an accurate SEQUENCE object */ - - THD *thd= table->in_use; if (table->s->tmp_table == NO_TMP_TABLE && thd->mdl_context.upgrade_shared_lock(table->mdl_ticket, MDL_EXCLUSIVE, @@ -255,6 +258,16 @@ int ha_sequence::write_row(const uchar *buf) sequence->write_lock(table); } +#ifdef WITH_WSREP + /* We need to start Galera transaction for select NEXT VALUE FOR + sequence if it is not yet started. Note that ALTER is handled + as TOI. */ + if (WSREP_ON && WSREP(thd) && + !thd->wsrep_trx().active() && + wsrep_thd_is_local(thd)) + wsrep_start_transaction(thd, thd->wsrep_next_trx_id()); +#endif + if (likely(!(error= file->update_first_row(buf)))) { Log_func *log_func= Write_rows_log_event::binlog_row_logging_function; -- cgit v1.2.1