From 87ae34ac834a601f7974219dbe131a13b12f3ac0 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 12 Dec 2023 08:57:11 +0100 Subject: [PATCH 01/38] galera: updating the list of disabled tests --- mysql-test/suite/galera/disabled.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 4db06714bc1..72be88fd1a1 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -24,4 +24,4 @@ galera_sst_mysqldump_with_key : MDEV-32782 galera_sst_mysqldump_with_key test fa mdev-31285 : MDEV-25089 Assertion `error.len > 0' failed in galera::ReplicatorSMM::handle_apply_error() galera_var_ignore_apply_errors : MENT-1997 galera_var_ignore_apply_errors test freezes MW-402 : temporarily disabled at the request of Codership -MDEV-22232 : temporarily disabled at the request of Codership +galera_desync_overlapped : MDEV-21538 galera_desync_overlapped MTR failed: Result content mismatch From 148cbf2aed16062c829ab87748800c0f9d9c817f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 12 Dec 2023 09:41:53 +0200 Subject: [PATCH 02/38] MDEV-32995 : Remove not supported tests from wsrep suite Changes to be committed: modified: mysql-test/suite/wsrep/disabled.def deleted: mysql-test/suite/wsrep/r/MDEV-22443.result deleted: mysql-test/suite/wsrep/r/MDEV-23092.result deleted: mysql-test/suite/wsrep/r/mdev_6832.result deleted: mysql-test/suite/wsrep/r/wsrep_variables_no_provider.result deleted: mysql-test/suite/wsrep/t/MDEV-22443.cnf deleted: mysql-test/suite/wsrep/t/MDEV-22443.test deleted: mysql-test/suite/wsrep/t/MDEV-23092.cnf deleted: mysql-test/suite/wsrep/t/MDEV-23092.test deleted: mysql-test/suite/wsrep/t/mdev_6832.cnf deleted: mysql-test/suite/wsrep/t/mdev_6832.test deleted: mysql-test/suite/wsrep/t/wsrep_variables_no_provider.cnf deleted: mysql-test/suite/wsrep/t/wsrep_variables_no_provider.test These test cases used feature not available anymore. Signed-off-by: Julius Goryavsky --- mysql-test/suite/wsrep/disabled.def | 4 -- mysql-test/suite/wsrep/r/MDEV-22443.result | 3 -- mysql-test/suite/wsrep/r/MDEV-23092.result | 13 ------ mysql-test/suite/wsrep/r/mdev_6832.result | 11 ----- .../r/wsrep_variables_no_provider.result | 44 ------------------- mysql-test/suite/wsrep/t/MDEV-22443.cnf | 8 ---- mysql-test/suite/wsrep/t/MDEV-22443.test | 12 ----- mysql-test/suite/wsrep/t/MDEV-23092.cnf | 8 ---- mysql-test/suite/wsrep/t/MDEV-23092.test | 22 ---------- mysql-test/suite/wsrep/t/mdev_6832.cnf | 7 --- mysql-test/suite/wsrep/t/mdev_6832.test | 17 ------- .../wsrep/t/wsrep_variables_no_provider.cnf | 12 ----- .../wsrep/t/wsrep_variables_no_provider.test | 38 ---------------- 13 files changed, 199 deletions(-) delete mode 100644 mysql-test/suite/wsrep/r/MDEV-22443.result delete mode 100644 mysql-test/suite/wsrep/r/MDEV-23092.result delete mode 100644 mysql-test/suite/wsrep/r/mdev_6832.result delete mode 100644 mysql-test/suite/wsrep/r/wsrep_variables_no_provider.result delete mode 100644 mysql-test/suite/wsrep/t/MDEV-22443.cnf delete mode 100644 mysql-test/suite/wsrep/t/MDEV-22443.test delete mode 100644 mysql-test/suite/wsrep/t/MDEV-23092.cnf delete mode 100644 mysql-test/suite/wsrep/t/MDEV-23092.test delete mode 100644 mysql-test/suite/wsrep/t/mdev_6832.cnf delete mode 100644 mysql-test/suite/wsrep/t/mdev_6832.test delete mode 100644 mysql-test/suite/wsrep/t/wsrep_variables_no_provider.cnf delete mode 100644 mysql-test/suite/wsrep/t/wsrep_variables_no_provider.test diff --git a/mysql-test/suite/wsrep/disabled.def b/mysql-test/suite/wsrep/disabled.def index 991109d72b8..f4145211680 100644 --- a/mysql-test/suite/wsrep/disabled.def +++ b/mysql-test/suite/wsrep/disabled.def @@ -11,7 +11,3 @@ ############################################################################## -mdev_6832: wsrep_provider is read-only for security reasons -MDEV-23092: wsrep_provider is read-only for security reasons -wsrep_variables_no_provider: wsrep_provider is read-only for security reasons -MDEV-22443: it is no longer allowed enable wsrep_on if wsrep_provider is 'none' diff --git a/mysql-test/suite/wsrep/r/MDEV-22443.result b/mysql-test/suite/wsrep/r/MDEV-22443.result deleted file mode 100644 index ea07cbec5a0..00000000000 --- a/mysql-test/suite/wsrep/r/MDEV-22443.result +++ /dev/null @@ -1,3 +0,0 @@ -SET SESSION wsrep_sync_wait=15; -SET SESSION wsrep_on=1; -START TRANSACTION READ WRITE; diff --git a/mysql-test/suite/wsrep/r/MDEV-23092.result b/mysql-test/suite/wsrep/r/MDEV-23092.result deleted file mode 100644 index d88aacf7d5c..00000000000 --- a/mysql-test/suite/wsrep/r/MDEV-23092.result +++ /dev/null @@ -1,13 +0,0 @@ -SET COLLATION_CONNECTION='utf16le_bin'; -SET GLOBAL wsrep_provider='/invalid/path/libgalera_smm.so'; -ERROR 42000: Variable 'wsrep_provider' can't be set to the value of '/' -SET GLOBAL wsrep_cluster_address='OFF'; -SET GLOBAL wsrep_slave_threads=10; -SELECT 1; -1 -1 -SET GLOBAL wsrep_cluster_address='gcomm://'; -SET GLOBAL wsrep_slave_threads=DEFAULT; -CALL mtr.add_suppression("wsrep_load()"); -CALL mtr.add_suppression("Failed to create a new provider"); -CALL mtr.add_suppression("Failed to load provider"); diff --git a/mysql-test/suite/wsrep/r/mdev_6832.result b/mysql-test/suite/wsrep/r/mdev_6832.result deleted file mode 100644 index 43894a6ec49..00000000000 --- a/mysql-test/suite/wsrep/r/mdev_6832.result +++ /dev/null @@ -1,11 +0,0 @@ -# -# MDEV-6832: ER_LOCK_WAIT_TIMEOUT on SHOW STATUS -# -SHOW STATUS LIKE 'wsrep_ready'; -Variable_name Value -wsrep_ready ON -SHOW STATUS LIKE 'wsrep_ready'; -Variable_name Value -wsrep_ready OFF -SET @@global.wsrep_cluster_address='gcomm://'; -# End of test. diff --git a/mysql-test/suite/wsrep/r/wsrep_variables_no_provider.result b/mysql-test/suite/wsrep/r/wsrep_variables_no_provider.result deleted file mode 100644 index ad35dc8dbcd..00000000000 --- a/mysql-test/suite/wsrep/r/wsrep_variables_no_provider.result +++ /dev/null @@ -1,44 +0,0 @@ -SELECT @@wsrep_on; -@@wsrep_on -1 -SET @wsrep_slave_threads_global_saved = @@global.wsrep_slave_threads; -SET @wsrep_debug_saved = @@global.wsrep_debug; -SET @wsrep_provider_options_saved= @@global.wsrep_provider_options; -SET @wsrep_cluster_address_saved= @@global.wsrep_cluster_address; -SET GLOBAL wsrep_provider=none; -SET SESSION wsrep_trx_fragment_size=DEFAULT; -ERROR HY000: Incorrect arguments to SET -SELECT @@session.wsrep_trx_fragment_size; -@@session.wsrep_trx_fragment_size -0 -SET GLOBAL wsrep_start_position='12345678-1234-1234-1234-123456789012:100'; -ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of '12345678-1234-1234-1234-123456789012:100' -SHOW WARNINGS; -Level Code Message -Warning 1231 Cannot set 'wsrep_start_position' because wsrep is switched off or provider is not loaded -Error 1231 Variable 'wsrep_start_position' can't be set to the value of '12345678-1234-1234-1234-123456789012:100' -SELECT @@global.wsrep_start_position; -@@global.wsrep_start_position -00000000-0000-0000-0000-000000000000:-1 -SET GLOBAL wsrep_debug=1; -Warnings: -Warning 1231 Setting 'wsrep_debug' has no effect because wsrep is switched off -SELECT @@global.wsrep_debug; -@@global.wsrep_debug -NONE -SET GLOBAL wsrep_slave_threads=5; -SELECT @@global.wsrep_slave_threads; -@@global.wsrep_slave_threads -5 -SET GLOBAL wsrep_desync=1; -ERROR HY000: WSREP (galera) not started -SELECT @@global.wsrep_desync; -@@global.wsrep_desync -0 -SET SESSION wsrep_trx_fragment_unit='rows'; -ERROR HY000: Incorrect arguments to SET -SELECT @@session.wsrep_trx_fragment_unit; -@@session.wsrep_trx_fragment_unit -rows -SET @@global.wsrep_slave_threads = @wsrep_slave_threads_global_saved; -SET @@global.wsrep_debug = @wsrep_debug_saved; diff --git a/mysql-test/suite/wsrep/t/MDEV-22443.cnf b/mysql-test/suite/wsrep/t/MDEV-22443.cnf deleted file mode 100644 index 851f2999a83..00000000000 --- a/mysql-test/suite/wsrep/t/MDEV-22443.cnf +++ /dev/null @@ -1,8 +0,0 @@ -!include ../my.cnf - -[mysqld.1] -wsrep-on=OFF -binlog-format=ROW -wsrep-provider=none -wsrep-cluster-address='gcomm://' -innodb_autoinc_lock_mode=2 diff --git a/mysql-test/suite/wsrep/t/MDEV-22443.test b/mysql-test/suite/wsrep/t/MDEV-22443.test deleted file mode 100644 index 674cb5ae2d8..00000000000 --- a/mysql-test/suite/wsrep/t/MDEV-22443.test +++ /dev/null @@ -1,12 +0,0 @@ -# -# MDEV-22443: terminate called after throwing an instance of -# 'wsrep::runtime_error' in std::terminate on START TRANSACTION -# - ---source include/have_innodb.inc ---source include/have_wsrep.inc ---source include/have_binlog_format_row.inc - -SET SESSION wsrep_sync_wait=15; -SET SESSION wsrep_on=1; -START TRANSACTION READ WRITE; diff --git a/mysql-test/suite/wsrep/t/MDEV-23092.cnf b/mysql-test/suite/wsrep/t/MDEV-23092.cnf deleted file mode 100644 index 851f2999a83..00000000000 --- a/mysql-test/suite/wsrep/t/MDEV-23092.cnf +++ /dev/null @@ -1,8 +0,0 @@ -!include ../my.cnf - -[mysqld.1] -wsrep-on=OFF -binlog-format=ROW -wsrep-provider=none -wsrep-cluster-address='gcomm://' -innodb_autoinc_lock_mode=2 diff --git a/mysql-test/suite/wsrep/t/MDEV-23092.test b/mysql-test/suite/wsrep/t/MDEV-23092.test deleted file mode 100644 index 92a6e392013..00000000000 --- a/mysql-test/suite/wsrep/t/MDEV-23092.test +++ /dev/null @@ -1,22 +0,0 @@ -# -# MDEV-23092: SIGABRT in wsrep::server_state::provider when setting -# invalid wsrep_provider (on optimized builds) -# - ---source include/have_innodb.inc ---source include/have_wsrep.inc ---source include/have_binlog_format_row.inc - -SET COLLATION_CONNECTION='utf16le_bin'; ---error 1231 -SET GLOBAL wsrep_provider='/invalid/path/libgalera_smm.so'; -SET GLOBAL wsrep_cluster_address='OFF'; -SET GLOBAL wsrep_slave_threads=10; -SELECT 1; - -SET GLOBAL wsrep_cluster_address='gcomm://'; -SET GLOBAL wsrep_slave_threads=DEFAULT; - -CALL mtr.add_suppression("wsrep_load()"); -CALL mtr.add_suppression("Failed to create a new provider"); -CALL mtr.add_suppression("Failed to load provider"); diff --git a/mysql-test/suite/wsrep/t/mdev_6832.cnf b/mysql-test/suite/wsrep/t/mdev_6832.cnf deleted file mode 100644 index 0bf01f81fc5..00000000000 --- a/mysql-test/suite/wsrep/t/mdev_6832.cnf +++ /dev/null @@ -1,7 +0,0 @@ -!include ../my.cnf - -[mysqld.1] -wsrep-on=ON -wsrep-provider=@ENV.WSREP_PROVIDER -wsrep-cluster-address=gcomm:// - diff --git a/mysql-test/suite/wsrep/t/mdev_6832.test b/mysql-test/suite/wsrep/t/mdev_6832.test deleted file mode 100644 index d5303ce3fcf..00000000000 --- a/mysql-test/suite/wsrep/t/mdev_6832.test +++ /dev/null @@ -1,17 +0,0 @@ ---source include/have_innodb.inc ---source include/have_wsrep_provider.inc ---source include/have_binlog_format_row.inc - ---echo # ---echo # MDEV-6832: ER_LOCK_WAIT_TIMEOUT on SHOW STATUS ---echo # - -SHOW STATUS LIKE 'wsrep_ready'; ---disable_query_log -eval SET @@global.wsrep_provider='$WSREP_PROVIDER'; ---enable_query_log -SHOW STATUS LIKE 'wsrep_ready'; -SET @@global.wsrep_cluster_address='gcomm://'; ---let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; ---source include/wait_condition.inc ---echo # End of test. diff --git a/mysql-test/suite/wsrep/t/wsrep_variables_no_provider.cnf b/mysql-test/suite/wsrep/t/wsrep_variables_no_provider.cnf deleted file mode 100644 index b73146d26e7..00000000000 --- a/mysql-test/suite/wsrep/t/wsrep_variables_no_provider.cnf +++ /dev/null @@ -1,12 +0,0 @@ -# Use default setting for mysqld processes -!include include/default_mysqld.cnf - -[mysqld.1] -wsrep-on=ON -binlog-format=ROW -wsrep-provider=@ENV.WSREP_PROVIDER -wsrep-cluster-address='gcomm://' -#galera_port=@OPT.port -#ist_port=@OPT.port -#sst_port=@OPT.port - diff --git a/mysql-test/suite/wsrep/t/wsrep_variables_no_provider.test b/mysql-test/suite/wsrep/t/wsrep_variables_no_provider.test deleted file mode 100644 index b44c9c5ebc8..00000000000 --- a/mysql-test/suite/wsrep/t/wsrep_variables_no_provider.test +++ /dev/null @@ -1,38 +0,0 @@ ---source include/have_wsrep.inc ---source include/have_innodb.inc - -SELECT @@wsrep_on; - -SET @wsrep_slave_threads_global_saved = @@global.wsrep_slave_threads; -SET @wsrep_debug_saved = @@global.wsrep_debug; -SET @wsrep_provider_options_saved= @@global.wsrep_provider_options; -SET @wsrep_cluster_address_saved= @@global.wsrep_cluster_address; - -SET GLOBAL wsrep_provider=none; - ---error ER_WRONG_ARGUMENTS -SET SESSION wsrep_trx_fragment_size=DEFAULT; -SELECT @@session.wsrep_trx_fragment_size; ---error ER_WRONG_VALUE_FOR_VAR -SET GLOBAL wsrep_start_position='12345678-1234-1234-1234-123456789012:100'; -SHOW WARNINGS; -SELECT @@global.wsrep_start_position; -SET GLOBAL wsrep_debug=1; -SELECT @@global.wsrep_debug; -SET GLOBAL wsrep_slave_threads=5; -SELECT @@global.wsrep_slave_threads; ---error ER_WRONG_ARGUMENTS -SET GLOBAL wsrep_desync=1; -SELECT @@global.wsrep_desync; ---error ER_WRONG_ARGUMENTS -SET SESSION wsrep_trx_fragment_unit='rows'; -SELECT @@session.wsrep_trx_fragment_unit; - ---disable_query_log -eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER'; -SET GLOBAL wsrep_cluster_address= @wsrep_cluster_address_saved; -SET GLOBAL wsrep_provider_options= @wsrep_provider_options_saved; ---source include/galera_wait_ready.inc -SET @@global.wsrep_slave_threads = @wsrep_slave_threads_global_saved; -SET @@global.wsrep_debug = @wsrep_debug_saved; ---enable_query_log From ddd8a90812e8ab7675b989696023e0a9966b6409 Mon Sep 17 00:00:00 2001 From: Denis Protivensky Date: Thu, 7 Dec 2023 15:35:27 +0300 Subject: [PATCH 03/38] MDEV-32964: Expect DB_INTERRUPTED from wsrep_row_upd_check_foreign_constraints Remove DB_LOCK_WAIT return code check as it should have been resolved to one of the other errors by that point. Signed-off-by: Julius Goryavsky --- storage/innobase/row/row0upd.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 58c93e4db0f..9a69c2948e7 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2486,18 +2486,18 @@ row_upd_sec_index_entry( case DB_NO_REFERENCED_ROW: err = DB_SUCCESS; break; - case DB_LOCK_WAIT: + case DB_INTERRUPTED: case DB_DEADLOCK: case DB_LOCK_WAIT_TIMEOUT: WSREP_DEBUG("Foreign key check fail: " "%s on table %s index %s query %s", - ut_strerr(err), index->name(), index->table->name.m_name, + ut_strerr(err), index->table->name.m_name, index->name(), wsrep_thd_query(trx->mysql_thd)); break; default: WSREP_ERROR("Foreign key check fail: " "%s on table %s index %s query %s", - ut_strerr(err), index->name(), index->table->name.m_name, + ut_strerr(err), index->table->name.m_name, index->name(), wsrep_thd_query(trx->mysql_thd)); break; } @@ -2506,7 +2506,7 @@ row_upd_sec_index_entry( } #ifdef WITH_WSREP - ut_ad(err == DB_SUCCESS || err == DB_LOCK_WAIT + ut_ad(err == DB_SUCCESS || err == DB_INTERRUPTED || err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT); #else ut_ad(err == DB_SUCCESS); From 0e1f4bd6610d2363982b0d0db918725d3d643753 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Thu, 12 Oct 2023 15:40:13 +0200 Subject: [PATCH 04/38] MDEV-31272 Statement rollback causes empty writeset replication This patch fixes cases where a transaction caused empty writeset to be replicated. This could happen in the case where a transaction executes a statement that initially manages to modify some data and therefore appended keys some for certification. The statement is however rolled back at some later stage due to some error (for example, a duplicate key error). After statement rollback the transaction is still alive, has no other changes. When committing such transaction, an empty writeset was replicated through Galera. The fix is to avoid calling into commit hook only when transaction has appended one or keys for certification *and* has some data in binlog cache to replicate. Otherwise, the commit is considered empty, and goes through usual empty commit path. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MDEV-31272.result | 36 ++++++++++++ .../suite/galera/t/MDEV-31272.combinations | 5 ++ mysql-test/suite/galera/t/MDEV-31272.test | 58 +++++++++++++++++++ sql/log.cc | 9 +++ sql/log.h | 1 + sql/wsrep_trans_observer.h | 8 ++- 6 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/MDEV-31272.result create mode 100644 mysql-test/suite/galera/t/MDEV-31272.combinations create mode 100644 mysql-test/suite/galera/t/MDEV-31272.test diff --git a/mysql-test/suite/galera/r/MDEV-31272.result b/mysql-test/suite/galera/r/MDEV-31272.result new file mode 100644 index 00000000000..e8469bc75c0 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-31272.result @@ -0,0 +1,36 @@ +connection node_2; +connection node_1; +connection node_1; +CREATE TABLE t1 (f1 int primary key, f2 int); +INSERT INTO t1 VALUES (1,0); +BEGIN; +INSERT INTO t1 VALUES (2,4),(1,1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +COMMIT; +Writesets replicated (expect 0) +0 +connection node_1; +SELECT * FROM t1; +f1 f2 +1 0 +connection node_2; +SELECT * FROM t1; +f1 f2 +1 0 +DROP TABLE t1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER); +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,4), (1,1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +Writesets replicated (expect 0) +0 +connection node_1; +SELECT * FROM t1; +f1 f2 +1 0 +connection node_2; +SELECT * FROM t1; +f1 f2 +1 0 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/MDEV-31272.combinations b/mysql-test/suite/galera/t/MDEV-31272.combinations new file mode 100644 index 00000000000..def4dda7def --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-31272.combinations @@ -0,0 +1,5 @@ +[binlogon] +log-bin +log-slave-updates=ON + +[binlogoff] diff --git a/mysql-test/suite/galera/t/MDEV-31272.test b/mysql-test/suite/galera/t/MDEV-31272.test new file mode 100644 index 00000000000..d2c823788a0 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-31272.test @@ -0,0 +1,58 @@ +# +# MDEV-31272: Statement rollback causes empty writeset replication +# + +--source include/galera_cluster.inc + +# +# Case 1: Multi statement transaction +# +--connection node_1 +CREATE TABLE t1 (f1 int primary key, f2 int); +INSERT INTO t1 VALUES (1,0); + +--let $replicated_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_replicated'` + +BEGIN; +--error ER_DUP_ENTRY +INSERT INTO t1 VALUES (2,4),(1,1); +COMMIT; + +--let $replicated_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_replicated'` + +--disable_query_log +--eval SELECT $replicated_new - $replicated_old AS 'Writesets replicated (expect 0)'; +--enable_query_log + +--connection node_1 +SELECT * FROM t1; +--connection node_2 +SELECT * FROM t1; + +DROP TABLE t1; + + +# +# Case 2: autocommit statement +# +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER); +INSERT INTO t1 VALUES (1,0); + +--let $replicated_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_replicated'` + +--error ER_DUP_ENTRY +INSERT INTO t1 VALUES (2,4), (1,1); + +--let $replicated_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_replicated'` + +--disable_query_log +--eval SELECT $replicated_new - $replicated_old AS 'Writesets replicated (expect 0)'; +--enable_query_log + +--connection node_1 +SELECT * FROM t1; +--connection node_2 +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/sql/log.cc b/sql/log.cc index 59730c3205a..ba5ebfbfabb 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -10894,6 +10894,15 @@ IO_CACHE *wsrep_get_cache(THD * thd, bool is_transactional) return NULL; } +bool wsrep_is_binlog_cache_empty(THD *thd) +{ + binlog_cache_mngr *cache_mngr= + (binlog_cache_mngr *) thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) + return cache_mngr->trx_cache.empty() && cache_mngr->stmt_cache.empty(); + return true; +} + void wsrep_thd_binlog_trx_reset(THD * thd) { DBUG_ENTER("wsrep_thd_binlog_trx_reset"); diff --git a/sql/log.h b/sql/log.h index 48169be0d68..cb3f205c1e9 100644 --- a/sql/log.h +++ b/sql/log.h @@ -1240,6 +1240,7 @@ static inline TC_LOG *get_tc_log_implementation() #ifdef WITH_WSREP IO_CACHE* wsrep_get_cache(THD *, bool); +bool wsrep_is_binlog_cache_empty(THD *); void wsrep_thd_binlog_trx_reset(THD * thd); void wsrep_thd_binlog_stmt_rollback(THD * thd); #endif /* WITH_WSREP */ diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h index cf5063df04d..5c5dc6fd174 100644 --- a/sql/wsrep_trans_observer.h +++ b/sql/wsrep_trans_observer.h @@ -88,7 +88,13 @@ static inline bool wsrep_is_real(THD* thd, bool all) */ static inline bool wsrep_has_changes(THD* thd) { - return (thd->wsrep_trx().is_empty() == false); + // Transaction has changes to replicate if it + // has appended one or more certification keys, + // and has actual changes to replicate in binlog + // cache. Except for streaming replication, + // where commit message may have no payload. + return !thd->wsrep_trx().is_empty() && + (!wsrep_is_binlog_cache_empty(thd) || thd->wsrep_trx().is_streaming()); } /* From 2b8c59fffaaf33455d2a226ecc209b5763c2b7bf Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 20 Dec 2023 14:51:00 +0300 Subject: [PATCH 05/38] Fix main.type_timestamp: Change 10.10 in "End of 10.10 tests" to 10.5 --- mysql-test/main/type_timestamp.result | 2 +- mysql-test/main/type_timestamp.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/type_timestamp.result b/mysql-test/main/type_timestamp.result index c78619fe585..f95a1d6ae39 100644 --- a/mysql-test/main/type_timestamp.result +++ b/mysql-test/main/type_timestamp.result @@ -1368,5 +1368,5 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; # -# End of 10.10 tests +# End of 10.5 tests # diff --git a/mysql-test/main/type_timestamp.test b/mysql-test/main/type_timestamp.test index abff4e69c22..526a0e69857 100644 --- a/mysql-test/main/type_timestamp.test +++ b/mysql-test/main/type_timestamp.test @@ -921,5 +921,5 @@ show create table t1; drop table t1; --echo # ---echo # End of 10.10 tests +--echo # End of 10.5 tests --echo # From 96e49c76a8f57a74e5d41322628b2fa5eea48739 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Wed, 20 Dec 2023 14:20:40 +0100 Subject: [PATCH 06/38] Revert "MDEV-32964: Expect DB_INTERRUPTED from wsrep_row_upd_check_foreign_constraints" This reverts commit ddd8a90812e8ab7675b989696023e0a9966b6409 (additional correction required) --- storage/innobase/row/row0upd.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 9a69c2948e7..58c93e4db0f 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2486,18 +2486,18 @@ row_upd_sec_index_entry( case DB_NO_REFERENCED_ROW: err = DB_SUCCESS; break; - case DB_INTERRUPTED: + case DB_LOCK_WAIT: case DB_DEADLOCK: case DB_LOCK_WAIT_TIMEOUT: WSREP_DEBUG("Foreign key check fail: " "%s on table %s index %s query %s", - ut_strerr(err), index->table->name.m_name, index->name(), + ut_strerr(err), index->name(), index->table->name.m_name, wsrep_thd_query(trx->mysql_thd)); break; default: WSREP_ERROR("Foreign key check fail: " "%s on table %s index %s query %s", - ut_strerr(err), index->table->name.m_name, index->name(), + ut_strerr(err), index->name(), index->table->name.m_name, wsrep_thd_query(trx->mysql_thd)); break; } @@ -2506,7 +2506,7 @@ row_upd_sec_index_entry( } #ifdef WITH_WSREP - ut_ad(err == DB_SUCCESS || err == DB_INTERRUPTED + ut_ad(err == DB_SUCCESS || err == DB_LOCK_WAIT || err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT); #else ut_ad(err == DB_SUCCESS); From cfaab614ea9bf0df4b5398c5d51f18cda8a9a00f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 19 Dec 2023 10:03:54 +0200 Subject: [PATCH 07/38] MDEV-24481 : galera_3nodes.galera_vote_rejoin_mysqldump MTR failed: mysql_shutdown failed Improve test case to wait until cluster membership is correct. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera_3nodes/disabled.def | 1 - .../r/galera_vote_rejoin_mysqldump.result | 12 +++++------ .../t/galera_vote_rejoin_mysqldump.test | 21 +++++++++---------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index 356f9dddb47..730f98667e6 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -12,7 +12,6 @@ galera_2_cluster : MDEV-32631 galera_2_cluster: before_rollback(): Assertion `0' failed galera_gtid_2_cluster : MDEV-32633 galera_gtid_2_cluster: Assertion `thd->wsrep_next_trx_id() != (0x7fffffffffffffffLL * 2ULL + 1)' -galera_vote_rejoin_mysqldump : MDEV-24481: galera_3nodes.galera_vote_rejoin_mysqldump MTR failed: mysql_shutdown failed galera_ssl_reload : MDEV-32778 galera_ssl_reload failed with warning message galera_ipv6_mariabackup : temporarily disabled at the request of Codership galera_pc_bootstrap : temporarily disabled at the request of Codership diff --git a/mysql-test/suite/galera_3nodes/r/galera_vote_rejoin_mysqldump.result b/mysql-test/suite/galera_3nodes/r/galera_vote_rejoin_mysqldump.result index e49a1714a3e..cacf1298058 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_vote_rejoin_mysqldump.result +++ b/mysql-test/suite/galera_3nodes/r/galera_vote_rejoin_mysqldump.result @@ -39,6 +39,9 @@ SELECT VARIABLE_VALUE AS expect_Disconnected FROM INFORMATION_SCHEMA.GLOBAL_STAT expect_Disconnected Disconnected SET SESSION wsrep_on=ON; +SELECT VARIABLE_VALUE AS expect_3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +expect_3 +3 SELECT VARIABLE_VALUE AS expect_Primary FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; expect_Primary Primary @@ -49,17 +52,11 @@ t1 CREATE TABLE `t1` ( `f1` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci connection node_2; -SET SESSION wsrep_on=OFF; -SET SESSION wsrep_on=ON; -# restart SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `f1` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci -SELECT COUNT(*) AS expect_0 FROM t1; -expect_0 -0 CALL mtr.add_suppression("is inconsistent with group"); connection node_3; SHOW CREATE TABLE t1; @@ -81,3 +78,6 @@ CALL mtr.add_suppression("Can't open and lock privilege tables"); CALL mtr.add_suppression("Info table is not ready to be used"); CALL mtr.add_suppression("Native table .* has the wrong structure"); CALL mtr.add_suppression("Table \'mysql.gtid_slave_pos\' doesn\'t exist"); +connection node_2; +# restart +connection node_1; diff --git a/mysql-test/suite/galera_3nodes/t/galera_vote_rejoin_mysqldump.test b/mysql-test/suite/galera_3nodes/t/galera_vote_rejoin_mysqldump.test index 70d58cb25f4..6c7b255bdc3 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_vote_rejoin_mysqldump.test +++ b/mysql-test/suite/galera_3nodes/t/galera_vote_rejoin_mysqldump.test @@ -59,6 +59,7 @@ SET SESSION wsrep_on=ON; --let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc +SELECT VARIABLE_VALUE AS expect_3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; SELECT VARIABLE_VALUE AS expect_Primary FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; # Confirm that the table is now identical throughout @@ -67,18 +68,7 @@ SELECT VARIABLE_VALUE AS expect_Primary FROM INFORMATION_SCHEMA.GLOBAL_STATUS WH SHOW CREATE TABLE t1; --connection node_2 -SET SESSION wsrep_on=OFF; ---let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; ---source include/wait_condition.inc ---source include/galera_wait_ready.inc -SET SESSION wsrep_on=ON; - -# restart node so we don't fail on WSREP_START_POSITION internal check ---source include/restart_mysqld.inc ---source include/wait_until_connected_again.inc - SHOW CREATE TABLE t1; -SELECT COUNT(*) AS expect_0 FROM t1; CALL mtr.add_suppression("is inconsistent with group"); --connection node_3 @@ -89,5 +79,14 @@ CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'PRIMARY'; check that col --connection node_1 --source suite/galera/include/galera_sst_restore.inc +--connection node_2 +# restart node so we don't fail on WSREP_START_POSITION internal check +--source include/restart_mysqld.inc +--source include/wait_until_connected_again.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + # Restore original auto_increment_offset values. --source ../galera/include/auto_increment_offset_restore.inc From c73417c68eb03e35c93e4896df3f3d2d4dd4bfc0 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 13 Dec 2023 14:43:41 +1100 Subject: [PATCH 08/38] MDEV-32986 Make regexp operator work in spider group by handler In spider_db_mbase_util::print_item_func(), if the sql item_func has an UNKNOWN_FUNC type, by default the spider group by handler (gbh) transform infix to prefix. But regexp should remain infix, so we add an if condition to account for this. --- .../spider/bugfix/r/mdev_32986.result | 23 +++++++++++++++ .../spider/bugfix/t/mdev_32986.test | 28 +++++++++++++++++++ storage/spider/spd_db_mysql.cc | 17 +++++++---- 3 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result new file mode 100644 index 00000000000..bdc580d421a --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_32986.result @@ -0,0 +1,23 @@ +# +# MDEV-32907 +# +for master_1 +for child2 +for child3 +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 (c varchar(16)); +create table t1 (c varchar(16)) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 values ('TestSpiderRegex'); +select c from t1 where c regexp '(Test|Spider|Regex)'; +c +TestSpiderRegex +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 +# +# end of test mdev_32907 +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test new file mode 100644 index 00000000000..94081d24ad8 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_32986.test @@ -0,0 +1,28 @@ +--echo # +--echo # MDEV-32907 +--echo # +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); + +create table t2 (c varchar(16)); +create table t1 (c varchar(16)) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; + +insert into t1 values ('TestSpiderRegex'); +select c from t1 where c regexp '(Test|Spider|Regex)'; +drop table t1, t2; +drop server srv; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log +--echo # +--echo # end of test mdev_32907 +--echo # diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 0bca68e0d4e..e689c9d93f0 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -5856,12 +5856,17 @@ int spider_db_mbase_util::print_item_func( item_count -= 2; break; } - } else if (func_name_length == 6 && - !strncasecmp("istrue", func_name, func_name_length) - ) { - last_str = SPIDER_SQL_IS_TRUE_STR; - last_str_length = SPIDER_SQL_IS_TRUE_LEN; - break; + } else if (func_name_length == 6) + { + if (!strncasecmp("istrue", func_name, func_name_length)) + { + last_str= SPIDER_SQL_IS_TRUE_STR; + last_str_length= SPIDER_SQL_IS_TRUE_LEN; + break; + } + else if (!strncasecmp("regexp", func_name, func_name_length)) + /* Keep the infix expression */ + break; } else if (func_name_length == 7) { if (!strncasecmp("isfalse", func_name, func_name_length)) From c712a5302b29d3e6a7d46fe4f22ea7cabb926d31 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 18 Dec 2023 22:13:23 +0100 Subject: [PATCH 09/38] fix test failures with ASAN ASAN uses *a lot* more stack. use not_asan.inc for tests that recursively put a lot of data on the stack --- mysql-test/main/execution_constants.test | 1 + mysql-test/main/func_regexp_pcre.test | 1 + mysql-test/main/lotofstack.result | 101 ++++++++++++++ mysql-test/main/lotofstack.test | 133 +++++++++++++++++++ mysql-test/main/sp_notembedded.result | 119 ----------------- mysql-test/main/sp_notembedded.test | 161 ----------------------- 6 files changed, 236 insertions(+), 280 deletions(-) create mode 100644 mysql-test/main/lotofstack.result create mode 100644 mysql-test/main/lotofstack.test diff --git a/mysql-test/main/execution_constants.test b/mysql-test/main/execution_constants.test index 285197cd1f4..49b1da8f8e9 100644 --- a/mysql-test/main/execution_constants.test +++ b/mysql-test/main/execution_constants.test @@ -1,5 +1,6 @@ # In embedded server we don't really have a control over stack usage -- source include/not_embedded.inc +-- source include/not_asan.inc # # Bug#21476: Lost Database Connection During Query diff --git a/mysql-test/main/func_regexp_pcre.test b/mysql-test/main/func_regexp_pcre.test index fdf5a7c2735..c5a6820d076 100644 --- a/mysql-test/main/func_regexp_pcre.test +++ b/mysql-test/main/func_regexp_pcre.test @@ -1,3 +1,4 @@ +--source include/not_asan.inc # 10.4 uses an old buggy PCRE library --disable_service_connection SET NAMES utf8; diff --git a/mysql-test/main/lotofstack.result b/mysql-test/main/lotofstack.result new file mode 100644 index 00000000000..553dcb3b1b4 --- /dev/null +++ b/mysql-test/main/lotofstack.result @@ -0,0 +1,101 @@ +create function bug10100f(prm int) returns int +begin +if prm > 1 then +return prm * bug10100f(prm - 1); +end if; +return 1; +end| +set statement sql_mode = '' for +create procedure bug10100p(prm int, inout res int) +begin +set res = res * prm; +if prm > 1 then +call bug10100p(prm - 1, res); +end if; +end| +set statement sql_mode = '' for +create procedure bug10100t(prm int) +begin +declare res int; +set res = 1; +call bug10100p(prm, res); +select res; +end| +create table t3 (a int)| +insert into t3 values (0)| +create view v1 as select a from t3| +create procedure bug10100pt(level int, lim int) +begin +if level < lim then +update t3 set a=level; +FLUSH TABLES; +call bug10100pt(level+1, lim); +else +select * from t3; +end if; +end| +create procedure bug10100pv(level int, lim int) +begin +if level < lim then +update v1 set a=level; +FLUSH TABLES; +call bug10100pv(level+1, lim); +else +select * from v1; +end if; +end| +prepare stmt2 from "select * from t3;"; +create procedure bug10100pd(level int, lim int) +begin +if level < lim then +select level; +prepare stmt1 from "update t3 set a=a+2"; +execute stmt1; +FLUSH TABLES; +execute stmt1; +FLUSH TABLES; +execute stmt1; +FLUSH TABLES; +deallocate prepare stmt1; +execute stmt2; +select * from t3; +call bug10100pd(level+1, lim); +else +execute stmt2; +end if; +end| +create procedure bug10100pc(level int, lim int) +begin +declare lv int; +declare c cursor for select a from t3; +open c; +if level < lim then +select level; +fetch c into lv; +select lv; +update t3 set a=level+lv; +FLUSH TABLES; +call bug10100pc(level+1, lim); +else +select * from t3; +end if; +close c; +end| +set @@max_sp_recursion_depth=255| +set @var=1| +call bug10100p(255, @var)| +call bug10100pt(1,255)| +call bug10100pv(1,255)| +call bug10100pd(1,255)| +call bug10100pc(1,255)| +set @@max_sp_recursion_depth=0| +deallocate prepare stmt2| +drop function bug10100f| +drop procedure bug10100p| +drop procedure bug10100t| +drop procedure bug10100pt| +drop procedure bug10100pv| +drop procedure bug10100pd| +drop procedure bug10100pc| +drop view v1| +drop table t3| diff --git a/mysql-test/main/lotofstack.test b/mysql-test/main/lotofstack.test new file mode 100644 index 00000000000..a658fb00e9f --- /dev/null +++ b/mysql-test/main/lotofstack.test @@ -0,0 +1,133 @@ +# +# For tests that need a lot of stack - they likely won't work under ASAN +# +source include/not_asan.inc; +source include/not_embedded.inc; + +# +# Bug#10100 function (and stored procedure?) recursivity problem +# +# routines with simple recursion +delimiter |; +create function bug10100f(prm int) returns int +begin + if prm > 1 then + return prm * bug10100f(prm - 1); + end if; + return 1; +end| +set statement sql_mode = '' for +create procedure bug10100p(prm int, inout res int) +begin + set res = res * prm; + if prm > 1 then + call bug10100p(prm - 1, res); + end if; +end| +set statement sql_mode = '' for +create procedure bug10100t(prm int) +begin + declare res int; + set res = 1; + call bug10100p(prm, res); + select res; +end| + +# a procedure which use tables and recursion +create table t3 (a int)| +insert into t3 values (0)| +create view v1 as select a from t3| +create procedure bug10100pt(level int, lim int) +begin + if level < lim then + update t3 set a=level; + FLUSH TABLES; + call bug10100pt(level+1, lim); + else + select * from t3; + end if; +end| +# view & recursion +create procedure bug10100pv(level int, lim int) +begin + if level < lim then + update v1 set a=level; + FLUSH TABLES; + call bug10100pv(level+1, lim); + else + select * from v1; + end if; +end| +# dynamic sql & recursion +prepare stmt2 from "select * from t3;"; +create procedure bug10100pd(level int, lim int) +begin + if level < lim then + select level; + prepare stmt1 from "update t3 set a=a+2"; + execute stmt1; + FLUSH TABLES; + execute stmt1; + FLUSH TABLES; + execute stmt1; + FLUSH TABLES; + deallocate prepare stmt1; + execute stmt2; + select * from t3; + call bug10100pd(level+1, lim); + else + execute stmt2; + end if; +end| +# cursor & recursion +create procedure bug10100pc(level int, lim int) +begin + declare lv int; + declare c cursor for select a from t3; + open c; + if level < lim then + select level; + fetch c into lv; + select lv; + update t3 set a=level+lv; + FLUSH TABLES; + call bug10100pc(level+1, lim); + else + select * from t3; + end if; + close c; +end| + +# end of the stack checking +set @@max_sp_recursion_depth=255| +set @var=1| +# disable log because error about stack overrun contains numbers which +# depend on a system +-- disable_ps_protocol +-- disable_result_log +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100p(255, @var)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pt(1,255)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pv(1,255)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pd(1,255)| +-- error ER_STACK_OVERRUN_NEED_MORE +call bug10100pc(1,255)| +-- enable_result_log +-- enable_ps_protocol +set @@max_sp_recursion_depth=0| + +deallocate prepare stmt2| + +drop function bug10100f| +drop procedure bug10100p| +drop procedure bug10100t| +drop procedure bug10100pt| +drop procedure bug10100pv| +drop procedure bug10100pd| +drop procedure bug10100pc| +drop view v1| +drop table t3| +delimiter ;| diff --git a/mysql-test/main/sp_notembedded.result b/mysql-test/main/sp_notembedded.result index e03361598a6..927e03d2a4d 100644 --- a/mysql-test/main/sp_notembedded.result +++ b/mysql-test/main/sp_notembedded.result @@ -1,7 +1,5 @@ set @old_concurrent_insert= @@global.concurrent_insert; set @@global.concurrent_insert= 0; -drop table if exists t1,t3; -drop procedure if exists bug4902| create procedure bug4902() begin show grants for 'root'@'localhost'; @@ -15,7 +13,6 @@ Grants for root@localhost GRANT ALL PRIVILEGES ON *.* TO `root`@`localhost` WITH GRANT OPTION GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION drop procedure bug4902| -drop procedure if exists bug4902_2| create procedure bug4902_2() begin show processlist; @@ -23,13 +20,10 @@ end| call bug4902_2()| show warnings| Level Code Message -Note 1305 PROCEDURE test.bug4902_2 does not exist call bug4902_2()| show warnings| Level Code Message -Note 1305 PROCEDURE test.bug4902_2 does not exist drop procedure bug4902_2| -drop procedure if exists bug6807| create procedure bug6807() begin declare a int; @@ -42,116 +36,6 @@ ERROR 70100: Query execution was interrupted call bug6807()| ERROR 70100: Query execution was interrupted drop procedure bug6807| -drop function if exists bug10100f| -drop procedure if exists bug10100p| -drop procedure if exists bug10100t| -drop procedure if exists bug10100pt| -drop procedure if exists bug10100pv| -drop procedure if exists bug10100pd| -drop procedure if exists bug10100pc| -create function bug10100f(prm int) returns int -begin -if prm > 1 then -return prm * bug10100f(prm - 1); -end if; -return 1; -end| -set statement sql_mode = '' for -create procedure bug10100p(prm int, inout res int) -begin -set res = res * prm; -if prm > 1 then -call bug10100p(prm - 1, res); -end if; -end| -set statement sql_mode = '' for -create procedure bug10100t(prm int) -begin -declare res int; -set res = 1; -call bug10100p(prm, res); -select res; -end| -create table t3 (a int)| -insert into t3 values (0)| -create view v1 as select a from t3| -create procedure bug10100pt(level int, lim int) -begin -if level < lim then -update t3 set a=level; -FLUSH TABLES; -call bug10100pt(level+1, lim); -else -select * from t3; -end if; -end| -create procedure bug10100pv(level int, lim int) -begin -if level < lim then -update v1 set a=level; -FLUSH TABLES; -call bug10100pv(level+1, lim); -else -select * from v1; -end if; -end| -prepare stmt2 from "select * from t3;"; -create procedure bug10100pd(level int, lim int) -begin -if level < lim then -select level; -prepare stmt1 from "update t3 set a=a+2"; -execute stmt1; -FLUSH TABLES; -execute stmt1; -FLUSH TABLES; -execute stmt1; -FLUSH TABLES; -deallocate prepare stmt1; -execute stmt2; -select * from t3; -call bug10100pd(level+1, lim); -else -execute stmt2; -end if; -end| -create procedure bug10100pc(level int, lim int) -begin -declare lv int; -declare c cursor for select a from t3; -open c; -if level < lim then -select level; -fetch c into lv; -select lv; -update t3 set a=level+lv; -FLUSH TABLES; -call bug10100pc(level+1, lim); -else -select * from t3; -end if; -close c; -end| -set @@max_sp_recursion_depth=255| -set @var=1| -call bug10100p(255, @var)| -call bug10100pt(1,255)| -call bug10100pv(1,255)| -call bug10100pd(1,255)| -call bug10100pc(1,255)| -set @@max_sp_recursion_depth=0| -deallocate prepare stmt2| -drop function bug10100f| -drop procedure bug10100p| -drop procedure bug10100t| -drop procedure bug10100pt| -drop procedure bug10100pv| -drop procedure bug10100pd| -drop procedure bug10100pc| -drop view v1| -drop table t3| -drop procedure if exists bug15298_1; -drop procedure if exists bug15298_2; create user 'mysqltest_1'@'localhost'; grant all privileges on test.* to 'mysqltest_1'@'localhost'; create procedure 15298_1 () sql security definer show grants for current_user; @@ -170,8 +54,6 @@ disconnect con1; drop user mysqltest_1@localhost; drop procedure 15298_1; drop procedure 15298_2; -drop table if exists t1; -drop procedure if exists p1; create table t1 (value varchar(15)); create procedure p1() update t1 set value='updated' where value='old'; call p1(); @@ -283,7 +165,6 @@ disconnect con2; # functions in databases which names contained dot. # connection default; -DROP DATABASE IF EXISTS `my.db`; create database `my.db`; use `my.db`; CREATE FUNCTION f1(a int) RETURNS INT RETURN a; diff --git a/mysql-test/main/sp_notembedded.test b/mysql-test/main/sp_notembedded.test index 29901c1221b..9aca03fbdc5 100644 --- a/mysql-test/main/sp_notembedded.test +++ b/mysql-test/main/sp_notembedded.test @@ -7,19 +7,12 @@ set @@global.concurrent_insert= 0; # Save the initial number of concurrent sessions --source include/count_sessions.inc ---disable_warnings -drop table if exists t1,t3; ---enable_warnings delimiter |; - # # Bug#4902 Stored procedure with SHOW WARNINGS leads to packet error # # Added tests for show grants command ---disable_warnings -drop procedure if exists bug4902| ---enable_warnings create procedure bug4902() begin show grants for 'root'@'localhost'; @@ -38,9 +31,6 @@ call bug4902()| drop procedure bug4902| # We need separate SP for SHOW PROCESSLIST since we want use replace_column ---disable_warnings -drop procedure if exists bug4902_2| ---enable_warnings create procedure bug4902_2() begin show processlist; @@ -58,9 +48,6 @@ drop procedure bug4902_2| # # Bug#6807 Stored procedure crash if CREATE PROCEDURE ... KILL QUERY # ---disable_warnings -drop procedure if exists bug6807| ---enable_warnings create procedure bug6807() begin declare a int; @@ -77,150 +64,11 @@ call bug6807()| drop procedure bug6807| - -# -# Bug#10100 function (and stored procedure?) recursivity problem -# ---disable_warnings -drop function if exists bug10100f| -drop procedure if exists bug10100p| -drop procedure if exists bug10100t| -drop procedure if exists bug10100pt| -drop procedure if exists bug10100pv| -drop procedure if exists bug10100pd| -drop procedure if exists bug10100pc| ---enable_warnings -# routines with simple recursion -create function bug10100f(prm int) returns int -begin - if prm > 1 then - return prm * bug10100f(prm - 1); - end if; - return 1; -end| -set statement sql_mode = '' for -create procedure bug10100p(prm int, inout res int) -begin - set res = res * prm; - if prm > 1 then - call bug10100p(prm - 1, res); - end if; -end| -set statement sql_mode = '' for -create procedure bug10100t(prm int) -begin - declare res int; - set res = 1; - call bug10100p(prm, res); - select res; -end| - -# a procedure which use tables and recursion -create table t3 (a int)| -insert into t3 values (0)| -create view v1 as select a from t3| -create procedure bug10100pt(level int, lim int) -begin - if level < lim then - update t3 set a=level; - FLUSH TABLES; - call bug10100pt(level+1, lim); - else - select * from t3; - end if; -end| -# view & recursion -create procedure bug10100pv(level int, lim int) -begin - if level < lim then - update v1 set a=level; - FLUSH TABLES; - call bug10100pv(level+1, lim); - else - select * from v1; - end if; -end| -# dynamic sql & recursion -prepare stmt2 from "select * from t3;"; -create procedure bug10100pd(level int, lim int) -begin - if level < lim then - select level; - prepare stmt1 from "update t3 set a=a+2"; - execute stmt1; - FLUSH TABLES; - execute stmt1; - FLUSH TABLES; - execute stmt1; - FLUSH TABLES; - deallocate prepare stmt1; - execute stmt2; - select * from t3; - call bug10100pd(level+1, lim); - else - execute stmt2; - end if; -end| -# cursor & recursion -create procedure bug10100pc(level int, lim int) -begin - declare lv int; - declare c cursor for select a from t3; - open c; - if level < lim then - select level; - fetch c into lv; - select lv; - update t3 set a=level+lv; - FLUSH TABLES; - call bug10100pc(level+1, lim); - else - select * from t3; - end if; - close c; -end| - -# end of the stack checking -set @@max_sp_recursion_depth=255| -set @var=1| -# disable log because error about stack overrun contains numbers which -# depend on a system --- disable_result_log --- error ER_STACK_OVERRUN_NEED_MORE -call bug10100p(255, @var)| --- error ER_STACK_OVERRUN_NEED_MORE -call bug10100pt(1,255)| --- error ER_STACK_OVERRUN_NEED_MORE -call bug10100pv(1,255)| --- error ER_STACK_OVERRUN_NEED_MORE -call bug10100pd(1,255)| --- error ER_STACK_OVERRUN_NEED_MORE -call bug10100pc(1,255)| --- enable_result_log -set @@max_sp_recursion_depth=0| - -deallocate prepare stmt2| - -drop function bug10100f| -drop procedure bug10100p| -drop procedure bug10100t| -drop procedure bug10100pt| -drop procedure bug10100pv| -drop procedure bug10100pd| -drop procedure bug10100pc| -drop view v1| -drop table t3| - delimiter ;| - # # Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context # ---disable_warnings -drop procedure if exists bug15298_1; -drop procedure if exists bug15298_2; ---enable_warnings create user 'mysqltest_1'@'localhost'; grant all privileges on test.* to 'mysqltest_1'@'localhost'; create procedure 15298_1 () sql security definer show grants for current_user; @@ -240,11 +88,6 @@ drop procedure 15298_2; # Bug#29936 Stored Procedure DML ignores low_priority_updates setting # ---disable_warnings -drop table if exists t1; -drop procedure if exists p1; ---enable_warnings - create table t1 (value varchar(15)); create procedure p1() update t1 set value='updated' where value='old'; @@ -409,10 +252,6 @@ DROP FUNCTION f1; connection default; ---disable_warnings -DROP DATABASE IF EXISTS `my.db`; ---enable_warnings - create database `my.db`; use `my.db`; From c8d52c895d0e5deb0e32113c8b51fed0bd03a8ab Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Dec 2023 09:49:40 +1100 Subject: [PATCH 10/38] MDEV-24670 memory pressure - warnings/notes Silence a few more un-actionable warnings. Use ignoring result on write to make sure compilers don't complain. --- storage/innobase/buf/buf0buf.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 0ca556f1c8e..23b5b776dce 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -847,8 +847,11 @@ public: { uint64_t u= 1; m_abort= true; - if (write(m_event_fd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) - sql_print_warning("InnoDB: Failed to write memory pressure quit message"); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" + /* return result ignored, cannot do anything with it */ + write(m_event_fd, &u, sizeof(uint64_t)); +#pragma GCC diagnostic pop } void join() @@ -893,11 +896,7 @@ void mem_pressure::pressure_routine(mem_pressure *m) if (errno == EINTR) continue; else - { - sql_print_warning("InnoDB: memory pressure poll error %s", - strerror(errno)); break; - } } if (!m->m_abort) break; From 425ecc74f86b19d24e3392bae052a3a9f6b41926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 19 Dec 2023 15:14:28 +0200 Subject: [PATCH 11/38] MDEV-29882 : Galera test failure on galera_sr_cc_master Test case changes only to wait expected membership and streaming replication status. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera_sr/disabled.def | 1 - .../galera_sr/r/galera_sr_cc_master.result | 30 ++++++++++--------- .../galera_sr/t/galera_sr_cc_master.test | 26 +++++++++++----- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/mysql-test/suite/galera_sr/disabled.def b/mysql-test/suite/galera_sr/disabled.def index fa62168d474..0371f0f589f 100644 --- a/mysql-test/suite/galera_sr/disabled.def +++ b/mysql-test/suite/galera_sr/disabled.def @@ -11,4 +11,3 @@ ############################################################################## GCF-1060 : MDEV-32160 GCF-1060 test failure due to wsrep MDL conflict -galera_sr_cc_master : MDEV-29882 Galera test failure on galera_sr_cc_master diff --git a/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result b/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result index 9e223414fe4..654b86d56a8 100644 --- a/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result +++ b/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result @@ -13,12 +13,12 @@ INSERT INTO t1 VALUES (2); INSERT INTO t1 VALUES (3); INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (5); -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; -COUNT(*) +SELECT COUNT(*) AS EXPECT_5 FROM mysql.wsrep_streaming_log; +EXPECT_5 5 connection node_1; -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; -COUNT(*) +SELECT COUNT(*) AS EXPECT_5 FROM mysql.wsrep_streaming_log; +EXPECT_5 5 connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2a; @@ -29,8 +29,8 @@ connection node_2; INSERT INTO t1 VALUES (6); ERROR HY000: Lost connection to MySQL server during query connection node_1; -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; -COUNT(*) +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +EXPECT_0 0 connection node_2a; connection node_1; @@ -38,8 +38,8 @@ connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2b; SELECT * FROM mysql.wsrep_streaming_log; node_uuid trx_id seqno flags frag -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; -COUNT(*) +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +EXPECT_0 0 SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -49,18 +49,20 @@ INSERT INTO t1 VALUES (3); INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (5); COMMIT; -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; -COUNT(*) +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +EXPECT_0 0 connection node_1; -SELECT COUNT(*) FROM t1; -COUNT(*) +SELECT COUNT(*) AS EXPECT_5 FROM t1; +EXPECT_5 5 -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; -COUNT(*) +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +EXPECT_0 0 DROP TABLE t1; connection node_2b; CALL mtr.add_suppression("WSREP: Failed to replicate rollback fragment for"); disconnect node_2; connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2; +disconnect node_2a; +disconnect node_2b; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test b/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test index da547c59626..f6a1b11cba9 100644 --- a/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test +++ b/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test @@ -28,10 +28,13 @@ INSERT INTO t1 VALUES (3); INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (5); -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +SELECT COUNT(*) AS EXPECT_5 FROM mysql.wsrep_streaming_log; --connection node_1 -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +--let $wait_condition = SELECT COUNT(*) = 5 FROM mysql.wsrep_streaming_log +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_5 FROM mysql.wsrep_streaming_log; # # Trigger CC . The transaction is aborted and we expect the SR tables to be cleaned up @@ -52,7 +55,9 @@ SET SESSION wsrep_sync_wait = DEFAULT; INSERT INTO t1 VALUES (6); --connection node_1 -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +--let $wait_condition = SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log +--source include/wait_condition.inc +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; # Restore cluster @@ -69,8 +74,10 @@ SELECT COUNT(*) FROM mysql.wsrep_streaming_log; --connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 --connection node_2b --source include/galera_wait_ready.inc +--let $wait_condition = SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log +--source include/wait_condition.inc SELECT * FROM mysql.wsrep_streaming_log; -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; # Repeat transaction to confirm no locks are left from previous transaction @@ -83,11 +90,13 @@ INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (5); COMMIT; -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; --connection node_1 -SELECT COUNT(*) FROM t1; -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1 +--source include/wait_condition.inc +SELECT COUNT(*) AS EXPECT_5 FROM t1; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; DROP TABLE t1; @@ -98,3 +107,6 @@ CALL mtr.add_suppression("WSREP: Failed to replicate rollback fragment for"); --connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2 # Restore original auto_increment_offset values. --source ../galera/include/auto_increment_offset_restore.inc + +--disconnect node_2a +--disconnect node_2b From dfd2eb529a9f8bae0e02d57763d36128a0696fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 20 Dec 2023 09:36:37 +0200 Subject: [PATCH 12/38] MDEV-29892 : Galera test failure on galera_sr_kill_slave_after_apply_rollback2 Could not reproduce and bug report is incomplete i.e. there is no error logs to analyze and 10.4 branch commit where failure was seen is not mentioned. Enable test to get more information. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera_3nodes_sr/disabled.def | 2 -- 1 file changed, 2 deletions(-) diff --git a/mysql-test/suite/galera_3nodes_sr/disabled.def b/mysql-test/suite/galera_3nodes_sr/disabled.def index 4472d960d9f..fcaf38a3d7b 100644 --- a/mysql-test/suite/galera_3nodes_sr/disabled.def +++ b/mysql-test/suite/galera_3nodes_sr/disabled.def @@ -9,5 +9,3 @@ # Do not use any TAB characters for whitespace. # ############################################################################## - -galera_sr_kill_slave_after_apply_rollback2 : MDEV-29892 Galera test failure on galera_sr_kill_slave_after_apply_rollback2 From 630972825f7fc10697476799ec2e2a6df10b58ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 20 Dec 2023 08:16:50 +0200 Subject: [PATCH 13/38] MDEV-29876 : Galera test failure on galera_sst_encrypted AES block cipher mode CTR is available at the moment only from OpenSSL 1.0.1. Do not run this testcase using CTR combination if it is not available. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/disabled.def | 1 - mysql-test/suite/galera/suite.pm | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 72be88fd1a1..ce251bac7ce 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -12,7 +12,6 @@ galera_as_slave_ctas : MDEV-28378 timeout galera_pc_recovery : MDEV-25199 cluster fails to start up -galera_sst_encrypted : MDEV-29876 Galera test failure on galera_sst_encrypted galera_var_node_address : MDEV-20485 Galera test failure galera_sequences : MDEV-32561 WSREP FSM failure: no such a transition REPLICATING -> COMMITTED galera_shutdown_nonprim : MDEV-32635 galera_shutdown_nonprim: mysql_shutdown failed diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index 027100fdb30..55108f603d3 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -70,13 +70,17 @@ push @::global_suppressions, sub which($) { return `sh -c "command -v $_[0]"` } sub skip_combinations { - my %skip = (); + my @combinations; + $skip{'include/have_mariabackup.inc'} = 'Need socket statistics utility' unless which("lsof") || which("sockstat") || which("ss"); $skip{'include/have_stunnel.inc'} = "Need 'stunnel' utility" unless which("stunnel"); $skip{'include/have_qpress.inc'} = "Need 'qpress' utility" unless which("qpress"); + $skip{'../encryption/include/have_file_key_management_plugin.combinations'} = [ 'ctr' ] + unless $::mysqld_variables{'version-ssl-library'} =~ /OpenSSL (\S+)/ + and $1 ge "1.0.1"; %skip; } From af69506de494ebccc230ec672a6926dbf09893c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 4 Dec 2023 11:21:58 +0200 Subject: [PATCH 14/38] Merge fixup encryption.corrupted_during_recovery Correctly merge 1ac03fd9142905e6585b97214cb14690f478c6a4 (superceding a52cd4aedac70676eb100afc8779eb694ccd8dce). Fixes up the merge commit fd0b47f9d6b4b7b9e600b12dd11738c810ad348e --- mysql-test/suite/encryption/r/corrupted_during_recovery.result | 2 +- mysql-test/suite/encryption/t/corrupted_during_recovery.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/encryption/r/corrupted_during_recovery.result b/mysql-test/suite/encryption/r/corrupted_during_recovery.result index 2b29bf260e1..7329999dd27 100644 --- a/mysql-test/suite/encryption/r/corrupted_during_recovery.result +++ b/mysql-test/suite/encryption/r/corrupted_during_recovery.result @@ -9,7 +9,7 @@ INSERT INTO t2 VALUES(2); SELECT * FROM t1; ERROR 42000: Unknown storage engine 'InnoDB' SELECT * FROM t1; -ERROR HY000: Table test/t1 is corrupted. Please drop the table and recreate. +Got one of the listed errors SELECT * FROM t2; a 2 diff --git a/mysql-test/suite/encryption/t/corrupted_during_recovery.test b/mysql-test/suite/encryption/t/corrupted_during_recovery.test index e4a31a0b478..1240ee1a8ff 100644 --- a/mysql-test/suite/encryption/t/corrupted_during_recovery.test +++ b/mysql-test/suite/encryption/t/corrupted_during_recovery.test @@ -60,7 +60,7 @@ call mtr.add_suppression("Table .*t1.* is corrupted. Please drop the table and r let $restart_parameters=--innodb_force_recovery=1 --skip-innodb-buffer-pool-load-at-startup; --source include/restart_mysqld.inc ---error ER_TABLE_CORRUPT +--error ER_NO_SUCH_TABLE_IN_ENGINE,ER_TABLE_CORRUPT SELECT * FROM t1; SELECT * FROM t2; CHECK TABLE t2; From 138cd311b4539d897621e4cfa0fc9ff18b8879ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 21 Dec 2023 11:57:21 +0200 Subject: [PATCH 15/38] Galera after-merge fix galera_sr.MDEV-28971: Adjust the expected error code. This fixes up the merge commit 2b99e5f7effb1fd8df6444fefcff1cb8994d8957 --- mysql-test/suite/galera_sr/t/MDEV-28971.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/galera_sr/t/MDEV-28971.test b/mysql-test/suite/galera_sr/t/MDEV-28971.test index 81238f94b4a..d3dbf03b4df 100644 --- a/mysql-test/suite/galera_sr/t/MDEV-28971.test +++ b/mysql-test/suite/galera_sr/t/MDEV-28971.test @@ -15,6 +15,6 @@ INSERT INTO t1 VALUES ('AAF'); SELECT SETVAL (SEQ, 100); ALTER TABLE t1 ADD CONSTRAINT constraint_1 UNIQUE (a); INSERT INTO t1 VALUES(); ---error ER_KEY_COLUMN_DOES_NOT_EXITS +--error ER_KEY_COLUMN_DOES_NOT_EXIST ALTER TABLE t1 ADD KEY(b (50)); DROP TABLE t1,SEQ; From 7cc332b7240bdd78efce787cbd63a3f7073cda3b Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 21 Dec 2023 01:55:25 +0100 Subject: [PATCH 16/38] MDEV-33046 - delete unnecessary synchronization with dict_stats_mutex Timer has internal synchronization, so that calling set_time concurrently is not a problem. --- storage/innobase/dict/dict0stats_bg.cc | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 280c5c1dec8..c3b8c8798c0 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -411,7 +411,6 @@ next_table_id: } static tpool::timer* dict_stats_timer; -static std::mutex dict_stats_mutex; static void dict_stats_func(void*) { @@ -422,26 +421,15 @@ static void dict_stats_func(void*) void dict_stats_start() { - std::lock_guard lk(dict_stats_mutex); - if (!dict_stats_timer) - dict_stats_timer= srv_thread_pool->create_timer(dict_stats_func); + DBUG_ASSERT(!dict_stats_timer); + dict_stats_timer= srv_thread_pool->create_timer(dict_stats_func); } static void dict_stats_schedule(int ms) { - std::unique_lock lk(dict_stats_mutex, std::defer_lock); - /* - Use try_lock() to avoid deadlock in dict_stats_shutdown(), which - uses dict_stats_mutex too. If there is simultaneous timer reschedule, - the first one will win, which is fine. - */ - if (!lk.try_lock()) - { - return; - } - if (dict_stats_timer) - dict_stats_timer->set_time(ms,0); + DBUG_ASSERT(dict_stats_timer); + dict_stats_timer->set_time(ms,0); } void dict_stats_schedule_now() @@ -452,7 +440,6 @@ void dict_stats_schedule_now() /** Shut down the dict_stats_thread. */ void dict_stats_shutdown() { - std::lock_guard lk(dict_stats_mutex); delete dict_stats_timer; dict_stats_timer= 0; } From ea0937d42a3a6fe328143e46c47e17f47caa57d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 21 Dec 2023 12:52:31 +0200 Subject: [PATCH 17/38] MDEV-30172: Tolerate CR_SSL_CONNECTION_ERROR in Galera tests We should treat CR_SERVER_LOST (2013) and CR_SSL_CONNECTION_ERROR (2026) interchangeably. --- .../galera/r/galera_gcache_recover_manytrx.result | 14 +++++++------- .../galera/t/galera_gcache_recover_manytrx.test | 14 +++++++------- mysql-test/suite/galera_3nodes_sr/r/GCF-832.result | 2 +- mysql-test/suite/galera_3nodes_sr/t/GCF-832.test | 2 +- mysql-test/suite/galera_sr/r/MDEV-27615.result | 2 +- mysql-test/suite/galera_sr/t/MDEV-27615.test | 3 ++- 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result b/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result index 76f16791eb7..de89168683a 100644 --- a/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result +++ b/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result @@ -100,19 +100,19 @@ Killing server ... connection node_1; Killing server ... connection node_1_insert_simple; -ERROR HY000: Lost connection to server during query +Got one of the listed errors connection node_1_insert_multi; -ERROR HY000: Lost connection to server during query +Got one of the listed errors connection node_1_insert_transaction; -ERROR HY000: Lost connection to server during query +Got one of the listed errors connection node_1_update_simple; -ERROR HY000: Lost connection to server during query +Got one of the listed errors connection node_1_insert_1k; -ERROR HY000: Lost connection to server during query +Got one of the listed errors connection node_1_insert_1m; -ERROR HY000: Lost connection to server during query +Got one of the listed errors connection node_1_insert_10m; -ERROR HY000: Lost connection to server during query +Got one of the listed errors connection node_1; Performing --wsrep-recover ... Using --wsrep-start-position when starting mysqld ... diff --git a/mysql-test/suite/galera/t/galera_gcache_recover_manytrx.test b/mysql-test/suite/galera/t/galera_gcache_recover_manytrx.test index e3921264f3d..b2c38b635f1 100644 --- a/mysql-test/suite/galera/t/galera_gcache_recover_manytrx.test +++ b/mysql-test/suite/galera/t/galera_gcache_recover_manytrx.test @@ -142,31 +142,31 @@ SET SESSION wsrep_sync_wait = 0; --source include/kill_galera.inc --connection node_1_insert_simple ---error 2013 +--error 2013, 2026 --reap --connection node_1_insert_multi ---error 2013 +--error 2013, 2026 --reap --connection node_1_insert_transaction ---error 2013 +--error 2013, 2026 --reap --connection node_1_update_simple ---error 2013 +--error 2013, 2026 --reap --connection node_1_insert_1k ---error 2013 +--error 2013, 2026 --reap --connection node_1_insert_1m ---error 2013 +--error 2013, 2026 --reap --connection node_1_insert_10m ---error 2013 +--error 2013, 2026 --reap --connection node_1 diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result index 726f70145f1..9043c66840d 100644 --- a/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result @@ -12,7 +12,7 @@ SET SESSION wsrep_trx_fragment_size=1; START TRANSACTION; INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); COMMIT; -ERROR HY000: Lost connection to server during query +Got one of the listed errors # restart connection node_1; SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test index ab8b62b969a..5da080a6c2c 100644 --- a/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test @@ -26,7 +26,7 @@ SET SESSION wsrep_trx_fragment_size=1; START TRANSACTION; INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); ---error 2013 +--error 2013,2026 COMMIT; --source include/start_mysqld.inc diff --git a/mysql-test/suite/galera_sr/r/MDEV-27615.result b/mysql-test/suite/galera_sr/r/MDEV-27615.result index e3bfd0ed539..8965cc8e99e 100644 --- a/mysql-test/suite/galera_sr/r/MDEV-27615.result +++ b/mysql-test/suite/galera_sr/r/MDEV-27615.result @@ -15,7 +15,7 @@ SET DEBUG_SYNC='now WAIT_FOR before_fragment'; SET GLOBAL wsrep_cluster_address = ''; SET DEBUG_SYNC = 'now SIGNAL continue'; connection node_2; -ERROR HY000: Lost connection to server during query +Got one of the listed errors connection node_2a; SELECT * FROM mysql.wsrep_streaming_log; node_uuid trx_id seqno flags frag diff --git a/mysql-test/suite/galera_sr/t/MDEV-27615.test b/mysql-test/suite/galera_sr/t/MDEV-27615.test index 121a85fb20c..8cc425aa7e1 100644 --- a/mysql-test/suite/galera_sr/t/MDEV-27615.test +++ b/mysql-test/suite/galera_sr/t/MDEV-27615.test @@ -43,7 +43,8 @@ SET DEBUG_SYNC = 'now SIGNAL continue'; # Disconnect causes connection to node_2 to be closed # --connection node_2 ---error 2013 # CR_SERVER_LOST +# CR_SERVER_LOST, CR_SSL_CONNECTION_ERROR +--error 2013,2026 --reap From cf86e075c046a13b8c0c8ced565990f313926440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 21 Dec 2023 12:58:39 +0200 Subject: [PATCH 18/38] Add an end-of-test marker --- mysql-test/main/type_timestamp.result | 1 + mysql-test/main/type_timestamp.test | 2 ++ 2 files changed, 3 insertions(+) diff --git a/mysql-test/main/type_timestamp.result b/mysql-test/main/type_timestamp.result index 6193359ce47..2b4aec726bb 100644 --- a/mysql-test/main/type_timestamp.result +++ b/mysql-test/main/type_timestamp.result @@ -1489,3 +1489,4 @@ indexed_col not_indexed_col DROP TABLE t2; DROP TABLE t1; SET note_verbosity=DEFAULT; +# End of 10.6 tests diff --git a/mysql-test/main/type_timestamp.test b/mysql-test/main/type_timestamp.test index 8410ef41aab..27de823851b 100644 --- a/mysql-test/main/type_timestamp.test +++ b/mysql-test/main/type_timestamp.test @@ -941,3 +941,5 @@ DELIMITER ;$$ --source unusable_keys_joins.inc DROP TABLE t1; SET note_verbosity=DEFAULT; + +--echo # End of 10.6 tests From c1cc264f12506554270e1379b8c68d50323252bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 21 Dec 2023 18:24:19 +0200 Subject: [PATCH 19/38] Fix an intermittent test failure --- mysql-test/suite/innodb/r/corrupted_during_recovery.result | 2 +- mysql-test/suite/innodb/t/corrupted_during_recovery.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/corrupted_during_recovery.result b/mysql-test/suite/innodb/r/corrupted_during_recovery.result index 951233ced3c..2cab795f6a1 100644 --- a/mysql-test/suite/innodb/r/corrupted_during_recovery.result +++ b/mysql-test/suite/innodb/r/corrupted_during_recovery.result @@ -9,7 +9,7 @@ INSERT INTO t2 VALUES(1); SELECT * FROM t1; ERROR 42000: Unknown storage engine 'InnoDB' SELECT * FROM t1; -ERROR 42S02: Table 'test.t1' doesn't exist in engine +Got one of the listed errors SELECT * FROM t2; a 1 diff --git a/mysql-test/suite/innodb/t/corrupted_during_recovery.test b/mysql-test/suite/innodb/t/corrupted_during_recovery.test index 31d353efa38..5b67bc3df1d 100644 --- a/mysql-test/suite/innodb/t/corrupted_during_recovery.test +++ b/mysql-test/suite/innodb/t/corrupted_during_recovery.test @@ -59,7 +59,7 @@ SELECT * FROM t1; let $restart_parameters=--innodb_force_recovery=1; --source include/restart_mysqld.inc ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_NO_SUCH_TABLE_IN_ENGINE,ER_TABLE_CORRUPT SELECT * FROM t1; SELECT * FROM t2; CHECK TABLE t2; From 1dc6ded8b19bd99b6fc2252070f94b7603eb4117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 19 Dec 2023 08:29:27 +0200 Subject: [PATCH 20/38] MDEV-20485 : Galera test failure on galera.galera_var_node_address Loopback interface might not be configured, thus do not test it. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/disabled.def | 2 +- .../r/galera_var_node_address.result | 20 +++++++++---------- .../t/galera_var_node_address.cnf | 4 +--- .../t/galera_var_node_address.test | 20 +++++++++---------- 4 files changed, 22 insertions(+), 24 deletions(-) rename mysql-test/suite/{galera => galera_3nodes}/r/galera_var_node_address.result (54%) rename mysql-test/suite/{galera => galera_3nodes}/t/galera_var_node_address.cnf (56%) rename mysql-test/suite/{galera => galera_3nodes}/t/galera_var_node_address.test (61%) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index ce251bac7ce..a05ee3f8880 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -12,7 +12,6 @@ galera_as_slave_ctas : MDEV-28378 timeout galera_pc_recovery : MDEV-25199 cluster fails to start up -galera_var_node_address : MDEV-20485 Galera test failure galera_sequences : MDEV-32561 WSREP FSM failure: no such a transition REPLICATING -> COMMITTED galera_shutdown_nonprim : MDEV-32635 galera_shutdown_nonprim: mysql_shutdown failed versioning_trx_id : MDEV-18590 : galera.versioning_trx_id: Test failure: mysqltest: Result content mismatch @@ -22,5 +21,6 @@ galera_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep: galera_sst_mysqldump_with_key : MDEV-32782 galera_sst_mysqldump_with_key test failed mdev-31285 : MDEV-25089 Assertion `error.len > 0' failed in galera::ReplicatorSMM::handle_apply_error() galera_var_ignore_apply_errors : MENT-1997 galera_var_ignore_apply_errors test freezes +MDEV-22232 : temporarily disabled at the request of Codership MW-402 : temporarily disabled at the request of Codership galera_desync_overlapped : MDEV-21538 galera_desync_overlapped MTR failed: Result content mismatch diff --git a/mysql-test/suite/galera/r/galera_var_node_address.result b/mysql-test/suite/galera_3nodes/r/galera_var_node_address.result similarity index 54% rename from mysql-test/suite/galera/r/galera_var_node_address.result rename to mysql-test/suite/galera_3nodes/r/galera_var_node_address.result index 6b91a9f3ea3..fe6c2a001b2 100644 --- a/mysql-test/suite/galera/r/galera_var_node_address.result +++ b/mysql-test/suite/galera_3nodes/r/galera_var_node_address.result @@ -1,22 +1,22 @@ connection node_2; connection node_1; -call mtr.add_suppression("WSREP: Stray state UUID msg: .*"); -call mtr.add_suppression("WSREP: Protocol violation. JOIN message sender .*"); -call mtr.add_suppression("WSREP: Sending JOIN failed: .*"); -flush tables; +connection node_1; SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE -4 -connection node_1; +3 CREATE TABLE t1 (f1 INTEGER) ENGINE=INNODB; connection node_2; -set global wsrep_sync_wait=15; INSERT INTO t1 VALUES (1); +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 +1 connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; connection node_3; -set global wsrep_sync_wait=15; -SELECT COUNT(*) FROM t1; -COUNT(*) +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 1 connection node_1; +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 +1 DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_node_address.cnf b/mysql-test/suite/galera_3nodes/t/galera_var_node_address.cnf similarity index 56% rename from mysql-test/suite/galera/t/galera_var_node_address.cnf rename to mysql-test/suite/galera_3nodes/t/galera_var_node_address.cnf index 0de0edaa396..aa0c47f1e0f 100644 --- a/mysql-test/suite/galera/t/galera_var_node_address.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_var_node_address.cnf @@ -1,4 +1,4 @@ -!include ../galera_4nodes.cnf +!include ../galera_3nodes.cnf [mysqld.2] wsrep_node_address=127.0.0.1 @@ -6,5 +6,3 @@ wsrep_node_address=127.0.0.1 [mysqld.3] wsrep_node_address=localhost -[mysqld.4] -wsrep_node_address=lo diff --git a/mysql-test/suite/galera/t/galera_var_node_address.test b/mysql-test/suite/galera_3nodes/t/galera_var_node_address.test similarity index 61% rename from mysql-test/suite/galera/t/galera_var_node_address.test rename to mysql-test/suite/galera_3nodes/t/galera_var_node_address.test index 99cb30e7b91..08c0d2e4d6e 100644 --- a/mysql-test/suite/galera/t/galera_var_node_address.test +++ b/mysql-test/suite/galera_3nodes/t/galera_var_node_address.test @@ -6,27 +6,27 @@ --source include/galera_cluster.inc --source include/have_innodb.inc -call mtr.add_suppression("WSREP: Stray state UUID msg: .*"); -call mtr.add_suppression("WSREP: Protocol violation. JOIN message sender .*"); -call mtr.add_suppression("WSREP: Sending JOIN failed: .*"); -flush tables; - ---let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; ---connection node_1 CREATE TABLE t1 (f1 INTEGER) ENGINE=INNODB; --connection node_2 -set global wsrep_sync_wait=15; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + INSERT INTO t1 VALUES (1); +SELECT COUNT(*) AS EXPECT_1 FROM t1; --connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 --connection node_3 -set global wsrep_sync_wait=15; -SELECT COUNT(*) FROM t1; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc +SELECT COUNT(*) AS EXPECT_1 FROM t1; --connection node_1 +SELECT COUNT(*) AS EXPECT_1 FROM t1; DROP TABLE t1; From 569381df8393d8bb0768c4755284f7590266cea4 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 21 Dec 2023 19:20:18 +0100 Subject: [PATCH 21/38] MDEV-33046 fixup. Do not try to schedule timer without dict_stats_start() dict_stats_schedule() is executed for --innodb-force-recovery=3+, but timer is not created. --- storage/innobase/dict/dict0stats_bg.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index c3b8c8798c0..72d23e126f8 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -428,8 +428,8 @@ void dict_stats_start() static void dict_stats_schedule(int ms) { - DBUG_ASSERT(dict_stats_timer); - dict_stats_timer->set_time(ms,0); + if(dict_stats_timer) + dict_stats_timer->set_time(ms,0); } void dict_stats_schedule_now() From 00a81516b084e9aa6f71bbc30eae6f4d1bd2f7ae Mon Sep 17 00:00:00 2001 From: tommijkl Date: Mon, 20 Jun 2022 15:24:22 +0300 Subject: [PATCH 22/38] MDEV-28953 sporadic failures with galera_sr.mysql-wsrep-features#165 Modified galera_sr.mysql-wsrep-features#165 test to be deterministic: Added one wait condition to catch execution state after --send command. Changed another wait condition to better match the execution state of the test thread. Signed-off-by: Julius Goryavsky --- .../galera_sr/r/mysql-wsrep-features#165.result | 16 ++++++++++++++++ .../galera_sr/t/mysql-wsrep-features#165.inc | 6 +++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result index 8ad3ac63438..353315d1dd6 100644 --- a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result @@ -26,6 +26,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -91,6 +92,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -156,6 +158,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -221,6 +224,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -286,6 +290,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -351,6 +356,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -416,6 +422,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -481,6 +488,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -546,6 +554,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -611,6 +620,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -676,6 +686,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -741,6 +752,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -806,6 +818,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -871,6 +884,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -936,6 +950,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 @@ -1001,6 +1016,7 @@ f1 f2 connection node_1c; SET AUTOCOMMIT=ON; INSERT INTO t1 VALUES (3, 'c'); +connection node_1; connection node_2; SELECT * FROM t1; f1 f2 diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc index 7f13afa3c47..26cdd116c08 100644 --- a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc @@ -46,6 +46,10 @@ SELECT * FROM t1; SET AUTOCOMMIT=ON; --send INSERT INTO t1 VALUES (3, 'c') +--connection node_1 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; +--source include/wait_condition.inc + --connection node_2 SELECT * FROM t1; @@ -54,7 +58,7 @@ SELECT * FROM t1; --send UPDATE t1 SET f2 = 'a' WHERE f1 = 2 --connection node_1 ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER != 'system user' AND STATE = 'Updating'; +--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; --source include/wait_condition.inc # Will deadlock From 91a118d55e610c474b0168340680ec0c9cd68779 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 21 Dec 2023 15:09:03 +0100 Subject: [PATCH 23/38] Cleanup - reuse background THD in dict_stats_func() Use static dict_stats_thd instead of creating/destroying it every time function is called. --- storage/innobase/dict/dict0stats_bg.cc | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index e820672f66e..3af9a7603cc 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -373,15 +373,18 @@ done: } static tpool::timer* dict_stats_timer; - +static THD *dict_stats_thd; static void dict_stats_func(void*) { - THD *thd= innobase_create_background_thd("InnoDB statistics"); - set_current_thd(thd); - while (dict_stats_process_entry_from_recalc_pool(thd)) {} - dict_defrag_process_entries_from_defrag_pool(thd); + if (!dict_stats_thd) + dict_stats_thd= innobase_create_background_thd("InnoDB statistics"); + set_current_thd(dict_stats_thd); + + while (dict_stats_process_entry_from_recalc_pool(dict_stats_thd)) {} + dict_defrag_process_entries_from_defrag_pool(dict_stats_thd); + + innobase_reset_background_thd(dict_stats_thd); set_current_thd(nullptr); - destroy_background_thd(thd); } @@ -408,4 +411,10 @@ void dict_stats_shutdown() { delete dict_stats_timer; dict_stats_timer= 0; + + if (dict_stats_thd) + { + destroy_background_thd(dict_stats_thd); + dict_stats_thd= 0; + } } From a31598b3b15155d7f8c007be59a6e4e2eb964901 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 21 Dec 2023 16:00:12 +0100 Subject: [PATCH 24/38] MDEV-33046 - reschedule dict_stats_func() if there work left to do. If recalc_pool is not empty, dict_stats needs to be rescheduled. Also revert aff5ed3988a3add17d607e6184288f82b567dbee --- storage/innobase/dict/dict0stats_bg.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 3af9a7603cc..54378951b19 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -361,17 +361,23 @@ done: { ut_ad(i->state == recalc::IN_PROGRESS); recalc_pool.erase(i); - const bool reschedule= !update_now && recalc_pool.empty(); if (err == DB_SUCCESS_LOCKED_REC) recalc_pool.emplace_back(recalc{table_id, recalc::IDLE}); mysql_mutex_unlock(&recalc_pool_mutex); - if (reschedule) - dict_stats_schedule(MIN_RECALC_INTERVAL * 1000); } return update_now; } +/** Check if the recalc pool is empty. */ +static bool is_recalc_pool_empty() +{ + mysql_mutex_lock(&recalc_pool_mutex); + bool empty= recalc_pool.empty(); + mysql_mutex_unlock(&recalc_pool_mutex); + return empty; +} + static tpool::timer* dict_stats_timer; static THD *dict_stats_thd; static void dict_stats_func(void*) @@ -385,6 +391,8 @@ static void dict_stats_func(void*) innobase_reset_background_thd(dict_stats_thd); set_current_thd(nullptr); + if (!is_recalc_pool_empty()) + dict_stats_schedule(MIN_RECALC_INTERVAL * 1000); } @@ -403,7 +411,7 @@ static void dict_stats_schedule(int ms) void dict_stats_schedule_now() { - dict_stats_schedule(10); + dict_stats_schedule(0); } /** Shut down the dict_stats_thread. */ From 91d53ea339ad17a8db016b1ee79f816d9502fa0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 12 Dec 2023 11:01:54 +0200 Subject: [PATCH 25/38] MDEV-33000: Fix test result file on some test cases Changes to be committed: modified: mysql-test/suite/galera/r/MW-388.result modified: mysql-test/suite/galera/r/MW-86-wait1.result modified: mysql-test/suite/galera/r/MW-86-wait8.result modified: mysql-test/suite/galera/r/galera_myisam_autocommit.result modified: mysql-test/suite/galera/r/galera_var_retry_autocommit.result modified: mysql-test/suite/galera/t/galera_myisam_autocommit.test These tests are run only using debug Galera library and changes are only test related. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MW-388.result | 2 +- mysql-test/suite/galera/r/MW-86-wait1.result | 4 ++-- mysql-test/suite/galera/r/MW-86-wait8.result | 4 ++-- mysql-test/suite/galera/r/galera_myisam_autocommit.result | 5 ++++- mysql-test/suite/galera/r/galera_var_retry_autocommit.result | 5 +---- mysql-test/suite/galera/t/galera_myisam_autocommit.test | 4 ++++ 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/galera/r/MW-388.result b/mysql-test/suite/galera/r/MW-388.result index b16addc542a..8dc473fae16 100644 --- a/mysql-test/suite/galera/r/MW-388.result +++ b/mysql-test/suite/galera/r/MW-388.result @@ -47,4 +47,4 @@ SET GLOBAL debug_dbug = NULL; SET debug_sync='RESET'; SELECT @@debug_sync; @@debug_sync -ON - current signal: '' +ON - current signals: '' diff --git a/mysql-test/suite/galera/r/MW-86-wait1.result b/mysql-test/suite/galera/r/MW-86-wait1.result index 8ad9c8bf181..f70e9e0a0fe 100644 --- a/mysql-test/suite/galera/r/MW-86-wait1.result +++ b/mysql-test/suite/galera/r/MW-86-wait1.result @@ -4,7 +4,7 @@ SET @orig_debug=@@debug_dbug; connection node_2; SELECT @@debug_sync; @@debug_sync -ON - current signal: '' +ON - current signals: '' set debug_sync='RESET'; SET SESSION wsrep_sync_wait = 1; SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb"; @@ -45,4 +45,4 @@ SET SESSION wsrep_sync_wait = default; DROP TABLE t_wait1; SELECT @@debug_sync; @@debug_sync -ON - current signal: '' +ON - current signals: '' diff --git a/mysql-test/suite/galera/r/MW-86-wait8.result b/mysql-test/suite/galera/r/MW-86-wait8.result index 07e59ebbe0a..f2aa34fa128 100644 --- a/mysql-test/suite/galera/r/MW-86-wait8.result +++ b/mysql-test/suite/galera/r/MW-86-wait8.result @@ -4,7 +4,7 @@ SET @orig_debug=@@debug_dbug; connection node_2; SELECT @@debug_sync; @@debug_sync -ON - current signal: '' +ON - current signals: '' SET SESSION wsrep_sync_wait = 8; SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb"; connection node_1; @@ -46,4 +46,4 @@ SET SESSION wsrep_sync_wait = default; DROP TABLE t_wait8; SELECT @@debug_sync; @@debug_sync -ON - current signal: '' +ON - current signals: '' diff --git a/mysql-test/suite/galera/r/galera_myisam_autocommit.result b/mysql-test/suite/galera/r/galera_myisam_autocommit.result index 6213e8f6380..b80af779430 100644 --- a/mysql-test/suite/galera/r/galera_myisam_autocommit.result +++ b/mysql-test/suite/galera/r/galera_myisam_autocommit.result @@ -1,5 +1,6 @@ connection node_2; connection node_1; +SET GLOBAL wsrep_mode=REPLICATE_MYISAM; CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (2), (3); @@ -22,6 +23,8 @@ COUNT(*) = 0 1 SELECT COUNT(*) = 0 FROM t2; COUNT(*) = 0 -1 +0 +connection node_1; DROP TABLE t1; DROP TABLE t2; +SET GLOBAL wsrep_mode=DEFAULT; diff --git a/mysql-test/suite/galera/r/galera_var_retry_autocommit.result b/mysql-test/suite/galera/r/galera_var_retry_autocommit.result index eee740b6036..50667b0a4fa 100644 --- a/mysql-test/suite/galera/r/galera_var_retry_autocommit.result +++ b/mysql-test/suite/galera/r/galera_var_retry_autocommit.result @@ -36,10 +36,7 @@ SET DEBUG_SYNC = 'now SIGNAL wsrep_retry_autocommit_continue'; connection node_1; SELECT COUNT(*) FROM t1; COUNT(*) -connection node_1; -SELECT COUNT(*) FROM t1; -COUNT(*) -0 +1 SET DEBUG_SYNC = 'RESET'; SET GLOBAL debug_dbug = NULL; DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_myisam_autocommit.test b/mysql-test/suite/galera/t/galera_myisam_autocommit.test index b01b5dc07f7..3452a06a16c 100644 --- a/mysql-test/suite/galera/t/galera_myisam_autocommit.test +++ b/mysql-test/suite/galera/t/galera_myisam_autocommit.test @@ -7,6 +7,8 @@ # Without a PK +SET GLOBAL wsrep_mode=REPLICATE_MYISAM; + CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; INSERT INTO t1 VALUES (1); @@ -41,5 +43,7 @@ TRUNCATE TABLE t1; SELECT COUNT(*) = 0 FROM t1; SELECT COUNT(*) = 0 FROM t2; +--connection node_1 DROP TABLE t1; DROP TABLE t2; +SET GLOBAL wsrep_mode=DEFAULT; From c89f769f2412202dd8d7e69b0942778c91602ec7 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Tue, 21 Nov 2023 15:43:11 +0200 Subject: [PATCH 26/38] MDEV-31905 GTID inconsistency This commit fixes GTID inconsistency which was injected by mariabackup SST. Donor node now writes new info file: donor_galera_info, which is streamed along the mariabackup donation to the joiner node. The donor_galera_info file contains both GTID and gtid domain_id, and joiner will use these to initialize the GTID state. Commit has new mtr test case: galera_3nodes.galera_gtid_consistency, which exercises potentially harmful mariabackup SST scenarios. The test has also scenario with IST joining. Signed-off-by: Julius Goryavsky --- extra/mariabackup/backup_copy.cc | 1 + extra/mariabackup/backup_copy.h | 1 + extra/mariabackup/backup_mysql.cc | 28 +- extra/mariabackup/wsrep.cc | 10 +- include/mysql/service_wsrep.h | 3 + .../include/galera_sst_method.combinations | 5 + mysql-test/include/galera_sst_method.inc | 4 + .../suite/galera_3nodes/r/MDEV-29171.result | 1 + .../r/galera_gtid_consistency.result | 219 +++++++++++ .../suite/galera_3nodes/t/MDEV-29171.test | 12 +- .../t/galera_gtid_consistency.cnf | 35 ++ .../t/galera_gtid_consistency.test | 346 ++++++++++++++++++ scripts/wsrep_sst_mariabackup.sh | 21 +- sql/service_wsrep.cc | 5 + sql/sql_plugin_services.inl | 3 +- sql/wsrep_dummy.cc | 2 + sql/wsrep_sst.cc | 11 + 17 files changed, 692 insertions(+), 15 deletions(-) create mode 100644 mysql-test/include/galera_sst_method.combinations create mode 100644 mysql-test/include/galera_sst_method.inc create mode 100644 mysql-test/suite/galera_3nodes/r/galera_gtid_consistency.result create mode 100644 mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.cnf create mode 100644 mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.test diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index c9c504c7e29..f4c1b5bc83a 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1674,6 +1674,7 @@ ibx_copy_incremental_over_full() NULL}; const char *sup_files[] = {"xtrabackup_binlog_info", "xtrabackup_galera_info", + "donor_galera_info", "xtrabackup_slave_info", "xtrabackup_info", "ib_lru_dump", diff --git a/extra/mariabackup/backup_copy.h b/extra/mariabackup/backup_copy.h index b4a323f2e89..b5aaf3121e9 100644 --- a/extra/mariabackup/backup_copy.h +++ b/extra/mariabackup/backup_copy.h @@ -9,6 +9,7 @@ /* special files */ #define XTRABACKUP_SLAVE_INFO "xtrabackup_slave_info" #define XTRABACKUP_GALERA_INFO "xtrabackup_galera_info" +#define XTRABACKUP_DONOR_GALERA_INFO "donor_galera_info" #define XTRABACKUP_BINLOG_INFO "xtrabackup_binlog_info" #define XTRABACKUP_INFO "xtrabackup_info" diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index 4f151b95941..e945037fea4 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -1424,6 +1424,7 @@ write_galera_info(ds_ctxt *datasink, MYSQL *connection) { char *state_uuid = NULL, *state_uuid55 = NULL; char *last_committed = NULL, *last_committed55 = NULL; + char *domain_id = NULL, *domain_id55 = NULL; bool result; mysql_variable status[] = { @@ -1434,6 +1435,12 @@ write_galera_info(ds_ctxt *datasink, MYSQL *connection) {NULL, NULL} }; + mysql_variable value[] = { + {"Wsrep_gtid_domain_id", &domain_id}, + {"wsrep_gtid_domain_id", &domain_id55}, + {NULL, NULL} + }; + /* When backup locks are supported by the server, we should skip creating xtrabackup_galera_info file on the backup stage, because wsrep_local_state_uuid and wsrep_last_committed will be inconsistent @@ -1452,9 +1459,26 @@ write_galera_info(ds_ctxt *datasink, MYSQL *connection) goto cleanup; } + read_mysql_variables(connection, "SHOW VARIABLES LIKE 'wsrep%'", value, true); + + if (domain_id == NULL && domain_id55 == NULL) { + msg("Warning: failed to get master wsrep state from SHOW VARIABLES."); + result = true; + goto cleanup; + } + result = datasink->backup_file_printf(XTRABACKUP_GALERA_INFO, - "%s:%s\n", state_uuid ? state_uuid : state_uuid55, - last_committed ? last_committed : last_committed55); + "%s:%s %s\n", state_uuid ? state_uuid : state_uuid55, + last_committed ? last_committed : last_committed55, + domain_id ? domain_id : domain_id55); + + if (result) + { + result= datasink->backup_file_printf(XTRABACKUP_DONOR_GALERA_INFO, + "%s:%s %s\n", state_uuid ? state_uuid : state_uuid55, + last_committed ? last_committed : last_committed55, + domain_id ? domain_id : domain_id55); + } if (result) { write_current_binlog_file(datasink, connection); diff --git a/extra/mariabackup/wsrep.cc b/extra/mariabackup/wsrep.cc index 1b93e9ed10e..acaf5c50e7c 100644 --- a/extra/mariabackup/wsrep.cc +++ b/extra/mariabackup/wsrep.cc @@ -53,6 +53,7 @@ permission notice: /*! Name of file where Galera info is stored on recovery */ #define XB_GALERA_INFO_FILENAME "xtrabackup_galera_info" +#define XB_GALERA_DONOR_INFO_FILENAME "donor_galera_info" /*********************************************************************** Store Galera checkpoint info in the 'xtrabackup_galera_info' file, if that @@ -67,7 +68,7 @@ xb_write_galera_info(bool incremental_prepare) long long seqno; MY_STAT statinfo; - /* Do not overwrite existing an existing file to be compatible with + /* Do not overwrite an existing file to be compatible with servers with older server versions */ if (!incremental_prepare && my_stat(XB_GALERA_INFO_FILENAME, &statinfo, MYF(0)) != NULL) { @@ -101,10 +102,11 @@ xb_write_galera_info(bool incremental_prepare) seqno = wsrep_xid_seqno(&xid); - msg("mariabackup: Recovered WSREP position: %s:%lld\n", - uuid_str, (long long) seqno); + msg("mariabackup: Recovered WSREP position: %s:%lld domain_id: %lld\n", + uuid_str, (long long) seqno, (long long)wsrep_get_domain_id()); - if (fprintf(fp, "%s:%lld", uuid_str, (long long) seqno) < 0) { + if (fprintf(fp, "%s:%lld %lld", uuid_str, (long long) seqno, + (long long)wsrep_get_domain_id()) < 0) { die( "could not write to " XB_GALERA_INFO_FILENAME diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h index f3588da4b46..a1897d76dc1 100644 --- a/include/mysql/service_wsrep.h +++ b/include/mysql/service_wsrep.h @@ -92,6 +92,7 @@ extern struct wsrep_service_st { void (*wsrep_thd_kill_LOCK_func)(const MYSQL_THD thd); void (*wsrep_thd_kill_UNLOCK_func)(const MYSQL_THD thd); void (*wsrep_thd_set_wsrep_PA_unsafe_func)(MYSQL_THD thd); + uint32 (*wsrep_get_domain_id_func)(); } *wsrep_service; #define MYSQL_SERVICE_WSREP_INCLUDED @@ -139,6 +140,7 @@ extern struct wsrep_service_st { #define wsrep_thd_set_ignored_error(T,V) wsrep_service->wsrep_thd_set_ignored_error_func(T,V) #define wsrep_report_bf_lock_wait(T,I) wsrep_service->wsrep_report_bf_lock_wait(T,I) #define wsrep_thd_set_PA_unsafe(T) wsrep_service->wsrep_thd_set_PA_unsafe_func(T) +#define wsrep_get_domain_id(T) wsrep_service->wsrep_get_domain_id_func(T) #else #define MYSQL_SERVICE_WSREP_STATIC_INCLUDED @@ -241,5 +243,6 @@ extern "C" void wsrep_report_bf_lock_wait(const THD *thd, unsigned long long trx_id); /* declare parallel applying unsafety for the THD */ extern "C" void wsrep_thd_set_PA_unsafe(MYSQL_THD thd); +extern "C" uint32 wsrep_get_domain_id(); #endif #endif /* MYSQL_SERVICE_WSREP_INCLUDED */ diff --git a/mysql-test/include/galera_sst_method.combinations b/mysql-test/include/galera_sst_method.combinations new file mode 100644 index 00000000000..14b6172e638 --- /dev/null +++ b/mysql-test/include/galera_sst_method.combinations @@ -0,0 +1,5 @@ +[rsync] +wsrep-sst-method=rsync + +[mariabackup] +wsrep_sst_method=mariabackup diff --git a/mysql-test/include/galera_sst_method.inc b/mysql-test/include/galera_sst_method.inc new file mode 100644 index 00000000000..99dd34531c7 --- /dev/null +++ b/mysql-test/include/galera_sst_method.inc @@ -0,0 +1,4 @@ +# The goal of including this file is to enable galera_sst_method combinations +# (see include/galera_sst_method.combinations) + +--source include/have_innodb.inc diff --git a/mysql-test/suite/galera_3nodes/r/MDEV-29171.result b/mysql-test/suite/galera_3nodes/r/MDEV-29171.result index 151be86d9cc..371ce006dd3 100644 --- a/mysql-test/suite/galera_3nodes/r/MDEV-29171.result +++ b/mysql-test/suite/galera_3nodes/r/MDEV-29171.result @@ -14,6 +14,7 @@ select @@wsrep_gtid_domain_id,@@wsrep_node_name; @@wsrep_gtid_domain_id @@wsrep_node_name 100 node3 connection node_3; +connection node_1; connection node_2; connection node_1; connection node_1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_gtid_consistency.result b/mysql-test/suite/galera_3nodes/r/galera_gtid_consistency.result new file mode 100644 index 00000000000..a35f31da422 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_gtid_consistency.result @@ -0,0 +1,219 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; +set wsrep_sync_wait=0; +connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; +set wsrep_sync_wait=0; +connection node_1; +CREATE PROCEDURE insert_row (IN node varchar(10), IN repeat_count int) +BEGIN +DECLARE current_num int; +SET current_num = 0; +WHILE current_num < repeat_count do +INSERT INTO t1(node, name) VALUES (node, UUID()); +SET current_num = current_num + 1; +END WHILE; +END| +CREATE TABLE t1 (id bigint not null primary key auto_increment, node VARCHAR(10), name VARCHAR(64)) ENGINE=innodb; +# node_1 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2 +connection node_2; +# node_2 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2 +connection node_3; +# node_3 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2 +connection node_1; +CALL insert_row('node1', 500);; +connection node_2; +CALL insert_row('node2', 500);; +connection node_3; +CALL insert_row('node3', 500);; +connection node_2; +# Shutdown node_2, force SST +connection node_2b; +# Wait until node_2 leaves cluster +connection node_1b; +connection node_1; +connection node_3; +connection node_1; +CALL insert_row('node1', 500); +connection node_3; +CALL insert_row('node3', 500); +CREATE TABLE t2(i int primary key) engine=innodb; +connection node_2; +# Restart node_2 +# restart +connection node_1b; +# Wait until node_2 is back in cluster +# node2 has joined +# GTID in node1 +show variables like 'wsrep_gtid_domain_id'; +Variable_name Value +wsrep_gtid_domain_id 1111 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2503 +connection node_2; +# GTID in node2 +show variables like 'wsrep_gtid_domain_id'; +Variable_name Value +wsrep_gtid_domain_id 1111 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2503 +connection node_3; +# GTID in node3 +show variables like 'wsrep_gtid_domain_id'; +Variable_name Value +wsrep_gtid_domain_id 1111 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2503 +# Shutdown node_3 +connection node_3; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; +# Wait until node_3 leaves cluster +connection node_1b; +connection node_1; +CALL insert_row('node1', 50); +CREATE TABLE t3(i int primary key) engine=innodb; +connection node_3; +# Rejoin node_3 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; +connection node_1b; +# Wait until node_3 is back in cluster +# node3 has joined +connection node_1; +# GTID in node1 +show variables like 'wsrep_gtid_domain_id'; +Variable_name Value +wsrep_gtid_domain_id 1111 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2554 +connection node_2; +# GTID in node2 +show variables like 'wsrep_gtid_domain_id'; +Variable_name Value +wsrep_gtid_domain_id 1111 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2554 +connection node_3; +# GTID in node3 +show variables like 'wsrep_gtid_domain_id'; +Variable_name Value +wsrep_gtid_domain_id 1111 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2554 +# One by one shutdown all nodes +connection node_3; +# shutdown node_3 +connection node_2; +# wait until node_3 is out of cluster +# shutdown node_2 +connection node_1; +# wait until node_2 is out of cluster +# shutdown node_1 +# Bootstrap from node_1 +connection node_1; +# restart: --wsrep_new_cluster +show variables like 'wsrep_gtid_domain_id'; +Variable_name Value +wsrep_gtid_domain_id 1111 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2554 +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +CALL insert_row('node1', 100);; +# Restart node_2 +connection node_2; +# restart +connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1; +set wsrep_sync_wait=0; +connection node_1c; +# wait until node_1 and node_2 are in cluster +connection node_2; +ALTER TABLE t2 ADD COLUMN (k int); +CALL insert_row('node2', 100);; +# Restart node_3 +connection node_3; +# restart +connection node_1c; +# wait until all nodes are back in cluster +after cluster restart +connection node_2; +connection node_1; +connection node_1; +node1 GTID +show variables like 'wsrep_gtid_domain_id'; +Variable_name Value +wsrep_gtid_domain_id 1111 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2756 +connection node_2; +node2 GTID +show variables like 'wsrep_gtid_domain_id'; +Variable_name Value +wsrep_gtid_domain_id 1111 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2756 +connection node_3; +node3 GTID +show variables like 'wsrep_gtid_domain_id'; +Variable_name Value +wsrep_gtid_domain_id 1111 +show variables like '%gtid_binlog_pos%'; +Variable_name Value +gtid_binlog_pos 1111-1-2756 +connection node_1; +table size in node1 +SELECT COUNT(*) FROM t1; +COUNT(*) +2750 +connection node_2; +table size in node2 +SELECT COUNT(*) FROM t1; +COUNT(*) +2750 +connection node_3; +table size in node3 +SELECT COUNT(*) FROM t1; +COUNT(*) +2750 +connection node_2; +call mtr.add_suppression("WSREP: Ignoring server id for non bootstrap node"); +call mtr.add_suppression("WSREP: Sending JOIN failed:.*"); +call mtr.add_suppression("Sending JOIN failed:.*"); +call mtr.add_suppression("WSREP: Failed to JOIN the cluster after SST.*"); +connection node_3; +call mtr.add_suppression("WSREP: Ignoring server id for non bootstrap node"); +call mtr.add_suppression("WSREP: Sending JOIN failed:.*"); +call mtr.add_suppression("Sending JOIN failed:.*"); +call mtr.add_suppression("WSREP: Failed to JOIN the cluster after SST.*"); +# cleanup +connection node_1; +DROP PROCEDURE insert_row; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +connection node_3; +connection node_2; +disconnect node_3; +disconnect node_2b; +disconnect node_1b; +disconnect node_1c; diff --git a/mysql-test/suite/galera_3nodes/t/MDEV-29171.test b/mysql-test/suite/galera_3nodes/t/MDEV-29171.test index 33fa4d722ae..bfb7abf9a8b 100644 --- a/mysql-test/suite/galera_3nodes/t/MDEV-29171.test +++ b/mysql-test/suite/galera_3nodes/t/MDEV-29171.test @@ -4,11 +4,13 @@ # --source include/galera_cluster.inc ---source include/have_innodb.inc +--source include/galera_sst_method.inc +--source include/force_restart.inc # # Initially wsrep gtid domain id is 100 # + --connection node_1 select @@wsrep_gtid_domain_id,@@wsrep_node_name; @@ -26,6 +28,10 @@ select @@wsrep_gtid_domain_id,@@wsrep_node_name; --connection node_3 --source include/shutdown_mysqld.inc +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + --connection node_2 --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc @@ -36,6 +42,7 @@ select @@wsrep_gtid_domain_id,@@wsrep_node_name; --source include/wait_condition.inc --source include/shutdown_mysqld.inc +--sleep 5 # # Bootstrap from node_1 and change wsrep_gtid_domain_id to 200 @@ -45,12 +52,11 @@ select @@wsrep_gtid_domain_id,@@wsrep_node_name; --source include/start_mysqld.inc show variables like 'wsrep_gtid_domain_id'; - # # Restart node_2, expect that wsrep_gtid_domain_id has changed to 200 # --connection node_2 ---let $restart_parameters = +--let $restart_parameters = --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect --source include/start_mysqld.inc show variables like 'wsrep_gtid_domain_id'; diff --git a/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.cnf b/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.cnf new file mode 100644 index 00000000000..5bd03178d1f --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.cnf @@ -0,0 +1,35 @@ +!include ../galera_3nodes.cnf + +[mysqld.1] +wsrep-node-name="node1" +wsrep_gtid_domain_id=1111 +gtid_domain_id=2 +server_id=10999 +wsrep_sst_auth="root:" +wsrep_sst_method=mariabackup +log_slave_updates=ON +log_bin=mariadb-bin-log +binlog-format=row +wsrep-gtid-mode=ON + +[mysqld.2] +wsrep-node-name="node2" +wsrep_gtid_domain_id=1112 +gtid_domain_id=3 +wsrep_sst_auth="root:" +wsrep_sst_method=mariabackup +log_slave_updates=ON +log_bin=mariadb-bin-log +binlog-format=row +wsrep-gtid-mode=ON + +[mysqld.3] +wsrep-node-name="node3" +wsrep_gtid_domain_id=1113 +gtid_domain_id=4 +wsrep_sst_auth="root:" +wsrep_sst_method=mariabackup +log_slave_updates=ON +log_bin=mariadb-bin-log +binlog-format=row +wsrep-gtid-mode=ON diff --git a/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.test b/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.test new file mode 100644 index 00000000000..f41230bc8e6 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.test @@ -0,0 +1,346 @@ +--source include/galera_cluster.inc +--source include/big_test.inc +--source include/force_restart.inc + + +# +# Testing gtid consistency in 3 node cluster when nodes drop +# and join back to cluster. +# The tests verify that wsrep_gtid_domain_id and gtid_binlog_pos +# remains same across the cluster +# In the configuration, nodes have different wsrep_gtid_domain_id +# but all nodes are supposed to receive effective domain id +# from the bootstrap node (node_1), and use it +# +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 +set wsrep_sync_wait=0; +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +set wsrep_sync_wait=0; + +--connection node_1 +DELIMITER |; +CREATE PROCEDURE insert_row (IN node varchar(10), IN repeat_count int) +BEGIN + DECLARE current_num int; + SET current_num = 0; + WHILE current_num < repeat_count do + INSERT INTO t1(node, name) VALUES (node, UUID()); + SET current_num = current_num + 1; + END WHILE; +END| +DELIMITER ;| + +CREATE TABLE t1 (id bigint not null primary key auto_increment, node VARCHAR(10), name VARCHAR(64)) ENGINE=innodb; + +# +# report initial gtid positions after table t1 is created +# +--echo # node_1 +show variables like '%gtid_binlog_pos%'; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1' +--source include/wait_condition.inc + +--echo # node_2 +show variables like '%gtid_binlog_pos%'; + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1' +--source include/wait_condition.inc + +--echo # node_3 +show variables like '%gtid_binlog_pos%'; + +########################################### +# scenario: join node 2 by SST +########################################## + +# +# start concurrent insert load and stop node2 while the load is on +# +--connection node_1 +--send CALL insert_row('node1', 500); + +--connection node_2 +--send CALL insert_row('node2', 500); + +--connection node_3 +--send CALL insert_row('node3', 500); + +# +# stop load to node 2 and shutdown the node, force SST +# +--connection node_2 +--reap + +--echo # Shutdown node_2, force SST +--connection node_2b +--source include/shutdown_mysqld.inc +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat + +--echo # Wait until node_2 leaves cluster +--connection node_1b +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# +# stop the remaining load to node 1 and 3 +# +--connection node_1 +--reap +--connection node_3 +--reap + +# +# some more inserts and DDL to nodes 1 and 3 +# while node 2 is absent +# +--connection node_1 +CALL insert_row('node1', 500); + +--connection node_3 +CALL insert_row('node3', 500); + +CREATE TABLE t2(i int primary key) engine=innodb; + +# +# restart node 2, should join by SST +# +--connection node_2 +--echo # Restart node_2 +--source include/start_mysqld.inc + +--connection node_1b +--echo # Wait until node_2 is back in cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--echo # node2 has joined + +# +# check gtid positions in all nodes +# +--echo # GTID in node1 +show variables like 'wsrep_gtid_domain_id'; +show variables like '%gtid_binlog_pos%'; + +--connection node_2 +--echo # GTID in node2 +show variables like 'wsrep_gtid_domain_id'; +show variables like '%gtid_binlog_pos%'; + +--connection node_3 +--echo # GTID in node3 +show variables like 'wsrep_gtid_domain_id'; +show variables like '%gtid_binlog_pos%'; + + +########################################### +# scenario: join node 3 by IST +########################################## + +--echo # Shutdown node_3 +--connection node_3 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; + +--echo # Wait until node_3 leaves cluster +--connection node_1b +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# +# do some inserts and DDL to node 1 +# while node 3 is absent +# +--connection node_1 +CALL insert_row('node1', 50); + +CREATE TABLE t3(i int primary key) engine=innodb; + +# +# remove isolation in node 3, should join by IST +# +--connection node_3 +--echo # Rejoin node_3 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; + +--connection node_1b +--echo # Wait until node_3 is back in cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--echo # node3 has joined + +# +# check gtid positions in all nodes +# +--connection node_1 +--echo # GTID in node1 +show variables like 'wsrep_gtid_domain_id'; +show variables like '%gtid_binlog_pos%'; + +--connection node_2 +--echo # GTID in node2 +show variables like 'wsrep_gtid_domain_id'; +show variables like '%gtid_binlog_pos%'; + +--connection node_3 +--echo # GTID in node3 +show variables like 'wsrep_gtid_domain_id'; +show variables like '%gtid_binlog_pos%'; + + +########################################### +# scenario: restart full custer +########################################## + + +# +# stop all nodes, one by one +# +--echo # One by one shutdown all nodes +--connection node_3 +--echo # shutdown node_3 +--source include/shutdown_mysqld.inc +--remove_file $MYSQLTEST_VARDIR/mysqld.3/data/grastate.dat + +--connection node_2 +--echo # wait until node_3 is out of cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +--echo # shutdown node_2 +--source include/shutdown_mysqld.inc +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat + +--connection node_1 +--echo # wait until node_2 is out of cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +--echo # shutdown node_1 +--source include/shutdown_mysqld.inc + +# +# bootstap cluster in order node1 - node2 - node3 +# send some inserts and DDL after each node started +# +--sleep 5 +--echo # Bootstrap from node_1 +--connection node_1 +--let $restart_parameters = --wsrep_new_cluster +--source include/start_mysqld.inc + +show variables like 'wsrep_gtid_domain_id'; +show variables like '%gtid_binlog_pos%'; + +ANALYZE TABLE t2; +--send CALL insert_row('node1', 100); + +--echo # Restart node_2 +--connection node_2 +--let $restart_parameters = +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--source include/start_mysqld.inc + +# +# connection node_1b may not be functional anymore, after node was +# shutdown, open node_1c for controlling node 1 state +# +--connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1 +set wsrep_sync_wait=0; +--connection node_1c +--echo # wait until node_1 and node_2 are in cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_2 +ALTER TABLE t2 ADD COLUMN (k int); +--send CALL insert_row('node2', 100); + + +--echo # Restart node_3 +--connection node_3 +--let $restart_parameters = +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.3.expect +--source include/start_mysqld.inc + +--connection node_1c +--echo # wait until all nodes are back in cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +--echo after cluster restart + +# stop load for nodes 1 and 2 +--connection node_2 +--reap + +--connection node_1 +--reap + +# +# check gtid positions in all nodes +# +--connection node_1 +--echo node1 GTID +show variables like 'wsrep_gtid_domain_id'; +show variables like '%gtid_binlog_pos%'; + +--connection node_2 +--echo node2 GTID +show variables like 'wsrep_gtid_domain_id'; +show variables like '%gtid_binlog_pos%'; + +--connection node_3 +--echo node3 GTID +show variables like 'wsrep_gtid_domain_id'; +show variables like '%gtid_binlog_pos%'; + +# +# check table size in all nodes +# +--connection node_1 +--echo table size in node1 +SELECT COUNT(*) FROM t1; + +--connection node_2 +--echo table size in node2 +SELECT COUNT(*) FROM t1; + +--connection node_3 +--echo table size in node3 +SELECT COUNT(*) FROM t1; + +# +# cleanups +# +--connection node_2 +call mtr.add_suppression("WSREP: Ignoring server id for non bootstrap node"); +call mtr.add_suppression("WSREP: Sending JOIN failed:.*"); +call mtr.add_suppression("Sending JOIN failed:.*"); +call mtr.add_suppression("WSREP: Failed to JOIN the cluster after SST.*"); +--connection node_3 +call mtr.add_suppression("WSREP: Ignoring server id for non bootstrap node"); +call mtr.add_suppression("WSREP: Sending JOIN failed:.*"); +call mtr.add_suppression("Sending JOIN failed:.*"); +call mtr.add_suppression("WSREP: Failed to JOIN the cluster after SST.*"); + +--echo # cleanup +--connection node_1 + +DROP PROCEDURE insert_row; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--source include/wait_condition.inc +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--source include/wait_condition.inc + +--disconnect node_3 +--disconnect node_2b +--disconnect node_1b +--disconnect node_1c diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 3dc7c0e3b69..2b05326e500 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -104,8 +104,10 @@ fi DATA="$WSREP_SST_OPT_DATA" INFO_FILE='xtrabackup_galera_info' +DONOR_INFO_FILE='donor_galera_info' IST_FILE='xtrabackup_ist' MAGIC_FILE="$DATA/$INFO_FILE" +DONOR_MAGIC_FILE="$DATA/$DONOR_INFO_FILE" INNOAPPLYLOG="$DATA/mariabackup.prepare.log" INNOMOVELOG="$DATA/mariabackup.move.log" @@ -651,14 +653,14 @@ get_stream() if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then strmcmd="'$STREAM_BIN' -x" else - strmcmd="'$STREAM_BIN' -c '$INFO_FILE'" + strmcmd="'$STREAM_BIN' -c '$INFO_FILE' '$DONOR_INFO_FILE'" fi else sfmt='tar' if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then strmcmd='tar xfi -' else - strmcmd="tar cf - '$INFO_FILE'" + strmcmd="tar cf - '$INFO_FILE' '$DONOR_INFO_FILE'" fi fi wsrep_log_info "Streaming with $sfmt" @@ -680,6 +682,7 @@ cleanup_at_exit() if [ $estatus -ne 0 ]; then wsrep_log_error "Removing $MAGIC_FILE file due to signal" [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" || : + [ -f "$DONOR_MAGIC_FILE" ] && rm -f "$DONOR_MAGIC_FILE" || : fi if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then @@ -916,6 +919,7 @@ monitor_process() } [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" +[ -f "$DONOR_MAGIC_FILE" ] && rm -rf "$DONOR_MAGIC_FILE" read_cnf setup_ports @@ -1048,7 +1052,7 @@ send_magic() # Store donor's wsrep GTID (state ID) and wsrep_gtid_domain_id # (separated by a space). echo "$WSREP_SST_OPT_GTID $WSREP_SST_OPT_GTID_DOMAIN_ID" > "$MAGIC_FILE" - + echo "$WSREP_SST_OPT_GTID $WSREP_SST_OPT_GTID_DOMAIN_ID" > "$DONOR_MAGIC_FILE" if [ -n "$WSREP_SST_OPT_REMOTE_PSWD" ]; then # Let joiner know that we know its secret echo "$SECRET_TAG $WSREP_SST_OPT_REMOTE_PSWD" >> "$MAGIC_FILE" @@ -1594,9 +1598,16 @@ else # joiner exit 2 fi + # use donor magic file, if present + # if IST was used, donor magic file was not created # Remove special tags from the magic file, and from the output: - coords=$(head -n1 "$MAGIC_FILE") - wsrep_log_info "Galera co-ords from recovery: $coords" + if [ -r "$DONOR_MAGIC_FILE" ]; then + coords=$(head -n1 "$DONOR_MAGIC_FILE") + wsrep_log_info "Galera co-ords from donor: $coords" + else + coords=$(head -n1 "$MAGIC_FILE") + wsrep_log_info "Galera co-ords from recovery: $coords" + fi echo "$coords" # Output : UUID:seqno wsrep_gtid_domain_id wsrep_log_info "Total time on joiner: $totime seconds" diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc index ccce076d8a9..8004e29c875 100644 --- a/sql/service_wsrep.cc +++ b/sql/service_wsrep.cc @@ -409,3 +409,8 @@ extern "C" void wsrep_thd_set_PA_unsafe(THD *thd) WSREP_DEBUG("session does not have active transaction, can not mark as PA unsafe"); } } + +extern "C" uint32 wsrep_get_domain_id() +{ + return wsrep_gtid_domain_id; +} diff --git a/sql/sql_plugin_services.inl b/sql/sql_plugin_services.inl index 60843a28fab..6b21f64bc64 100644 --- a/sql/sql_plugin_services.inl +++ b/sql/sql_plugin_services.inl @@ -181,7 +181,8 @@ static struct wsrep_service_st wsrep_handler = { wsrep_report_bf_lock_wait, wsrep_thd_kill_LOCK, wsrep_thd_kill_UNLOCK, - wsrep_thd_set_PA_unsafe + wsrep_thd_set_PA_unsafe, + wsrep_get_domain_id }; static struct thd_specifics_service_st thd_specifics_handler= diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index a67da77c472..da3812d29f5 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -161,3 +161,5 @@ void wsrep_report_bf_lock_wait(const THD*, void wsrep_thd_set_PA_unsafe(THD*) {} +uint32 wsrep_get_domain_id() +{ return 0;} diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 5a69bca0ae6..08a3d159e94 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -652,7 +652,9 @@ static void* sst_joiner_thread (void* a) else { // Read state ID (UUID:SEQNO) followed by wsrep_gtid_domain_id (if any). + unsigned long int domain_id= wsrep_gtid_domain_id; const char *pos= strchr(out, ' '); + WSREP_DEBUG("SST state ID tmp=%s out=%s pos=%p", tmp, out, pos); if (!pos) { @@ -662,6 +664,13 @@ static void* sst_joiner_thread (void* a) WSREP_WARN("Did not find domain ID from SST script output '%s'. " "Domain ID must be set manually to keep binlog consistent", out); + if (wsrep_gtid_domain_id) + { + WSREP_INFO("This node is configured to use wsrep_gtid_domain_id=%lu by user.", + domain_id); + wsrep_gtid_server.domain_id= (uint32)domain_id; + wsrep_gtid_domain_id= (uint32)domain_id; + } } err= sst_scan_uuid_seqno (out, &ret_uuid, &ret_seqno); @@ -1688,6 +1697,8 @@ static int sst_flush_tables(THD* thd) char content[100]; snprintf(content, sizeof(content), "%s:%lld %d\n", wsrep_cluster_state_uuid, (long long)wsrep_locked_seqno, wsrep_gtid_server.domain_id); + WSREP_DEBUG("sst_flush_tables : %s:%lld %d", wsrep_cluster_state_uuid, + (long long)wsrep_locked_seqno, wsrep_gtid_server.domain_id); err= sst_create_file(flush_success, content); if (err) From 362c0950e8999a88f5866fc7361e10615364e4a3 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Mon, 23 Oct 2023 11:49:47 +0200 Subject: [PATCH 27/38] MDEV-32549 Cluster inconsistent after SAVEPOINT is rolled back Attempting to set a SAVEPOINT when one of the involved storage engines does not support savepoints, raises an error, and results in statement rollback. If Galera is enabled with binlog emulation, the above scenario was not handled correctly, and resulted in cluster wide inconsistency. The problem was in wsrep_register_binlog_handler(), which is called towards the beginning of SAVEPOINT execution. This function is supposed to mark the beginning of statement position in trx cache through `set_prev_position()`. However, it did so only on condition that `get_prev_position()` returns `MY_OFF_T_UNDEF`. This before statement position is typically reset to undefined at the end of statement in `binlog_commit()` / `binlog_rollback()`. However that's not the case with Galera and binlog emulation, for which binlog commit / rollback hooks are not called due to the optimization that avoids internal 2PC (MDEV-16509). Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MDEV-32549.result | 24 ++++++++++++++++++ mysql-test/suite/galera/t/MDEV-32549.test | 28 +++++++++++++++++++++ sql/log.cc | 9 +++---- 3 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/galera/r/MDEV-32549.result create mode 100644 mysql-test/suite/galera/t/MDEV-32549.test diff --git a/mysql-test/suite/galera/r/MDEV-32549.result b/mysql-test/suite/galera/r/MDEV-32549.result new file mode 100644 index 00000000000..65c81819d27 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-32549.result @@ -0,0 +1,24 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) engine=innodb; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) engine=aria; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +SELECT * FROM t2; +f1 +SAVEPOINT s1; +ERROR 42000: The storage engine for the table doesn't support SAVEPOINT +INSERT INTO t1 VALUES (2); +COMMIT; +connection node_1; +SELECT * FROM t1; +f1 +1 +2 +connection node_2; +SELECT * FROM t1; +f1 +1 +2 +connection node_1; +DROP TABLE t1,t2; diff --git a/mysql-test/suite/galera/t/MDEV-32549.test b/mysql-test/suite/galera/t/MDEV-32549.test new file mode 100644 index 00000000000..a2faa46da5f --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-32549.test @@ -0,0 +1,28 @@ +# +# MDEV-32549: Cluster is inconsitent after savepoint +# statement is rolled back +# +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) engine=innodb; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) engine=aria; + +START TRANSACTION; +INSERT INTO t1 VALUES (1); +SELECT * FROM t2; +--error ER_CHECK_NOT_IMPLEMENTED +SAVEPOINT s1; +INSERT INTO t1 VALUES (2); +COMMIT; + +--connection node_1 +SELECT * FROM t1; + +# If bug is present: only the second INSERT +# is replicated, causing an inconsistent +# cluster. +--connection node_2 +SELECT * FROM t1; + +--connection node_1 +DROP TABLE t1,t2; diff --git a/sql/log.cc b/sql/log.cc index aacf773fa65..3d3ac9b2b35 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -11257,12 +11257,9 @@ void wsrep_register_binlog_handler(THD *thd, bool trx) /* Set an implicit savepoint in order to be able to truncate a trx-cache. */ - if (cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF) - { - my_off_t pos= 0; - binlog_trans_log_savepos(thd, &pos); - cache_mngr->trx_cache.set_prev_position(pos); - } + my_off_t pos= 0; + binlog_trans_log_savepos(thd, &pos); + cache_mngr->trx_cache.set_prev_position(pos); /* Set callbacks in order to be able to call commmit or rollback. From bdaa6bac05b2c0cfb8a974a798775a88e124e2de Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 22 Dec 2023 14:17:26 +1100 Subject: [PATCH 28/38] [fixup] Spider: correct init queries after merge The merge e95bba9c58c0f08bdc6ce031d11fb5b52e814e53 missed it --- storage/spider/spd_init_query.h | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index 04c9a47e9f2..5e084e3c27c 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -652,6 +652,46 @@ static LEX_STRING spider_init_queries[] = { "alter table mysql.spider_xa_member" " add column if not exists dsn char(64) default null after default_group;" )}, + {C_STRING_WITH_LEN( + "alter table mysql.spider_link_mon_servers" + " add column if not exists filedsn text default null after dsn," + " algorithm=copy, lock=shared;" + )}, + {C_STRING_WITH_LEN( + "alter table mysql.spider_tables" + " add column if not exists filedsn text default null after dsn," + " algorithm=copy, lock=shared;" + )}, + {C_STRING_WITH_LEN( + "alter table mysql.spider_xa_failed_log" + " add column if not exists filedsn text default null after dsn," + " algorithm=copy, lock=shared;" + )}, + {C_STRING_WITH_LEN( + "alter table mysql.spider_xa_member" + " add column if not exists filedsn text default null after dsn," + " algorithm=copy, lock=shared;" + )}, + {C_STRING_WITH_LEN( + "alter table mysql.spider_link_mon_servers" + " add column if not exists driver char(64) default null after filedsn," + " algorithm=copy, lock=shared;" + )}, + {C_STRING_WITH_LEN( + "alter table mysql.spider_tables" + " add column if not exists driver char(64) default null after filedsn," + " algorithm=copy, lock=shared;" + )}, + {C_STRING_WITH_LEN( + "alter table mysql.spider_xa_failed_log" + " add column if not exists driver char(64) default null after filedsn," + " algorithm=copy, lock=shared;" + )}, + {C_STRING_WITH_LEN( + "alter table mysql.spider_xa_member" + " add column if not exists driver char(64) default null after filedsn," + " algorithm=copy, lock=shared;" + )}, {C_STRING_WITH_LEN( "set @win_plugin := IF(@@version_compile_os like 'Win%', 1, 0);" )}, From c554f2683201df4731b1e3c61fb5011d7d8bbb86 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Tue, 24 Oct 2023 16:04:47 +0200 Subject: [PATCH 29/38] Disable ps-protocol second execution on test that do not support it MDEV-31003 has introduced second execution for SELECTs that execute under ps-protocol. The following tests in galera suites do not support this mode of execution, disable it: galera.MDEV-27862 galera.galera_log_output_csv galera.galera_query_cache galera.galera_query_cache_sync_wait galera_3nodes_sr.GCF-336 galera_3nodes_sr.galera_sr_isolate_master galera_sr.galera_sr_large_fragment galera_sr.galera_sr_many_fragments Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/t/MDEV-27862.test | 3 +++ mysql-test/suite/galera/t/galera_log_output_csv.test | 4 ++++ mysql-test/suite/galera/t/galera_query_cache.test | 3 +++ mysql-test/suite/galera/t/galera_query_cache_sync_wait.test | 4 ++++ mysql-test/suite/galera_3nodes_sr/t/GCF-336.test | 5 +++++ .../suite/galera_3nodes_sr/t/galera_sr_isolate_master.test | 2 ++ mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test | 3 +++ mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test | 4 ++++ 8 files changed, 28 insertions(+) diff --git a/mysql-test/suite/galera/t/MDEV-27862.test b/mysql-test/suite/galera/t/MDEV-27862.test index d23ce95d47e..f19d6b5db42 100644 --- a/mysql-test/suite/galera/t/MDEV-27862.test +++ b/mysql-test/suite/galera/t/MDEV-27862.test @@ -1,6 +1,8 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +--disable_ps2_protocol + # NEXTVAL --connection node_1 @@ -54,3 +56,4 @@ SELECT NEXTVAL(seq_transaction) = 4; DROP SEQUENCE seq_transaction; DROP TABLE t1; +--enable_ps2_protocol diff --git a/mysql-test/suite/galera/t/galera_log_output_csv.test b/mysql-test/suite/galera/t/galera_log_output_csv.test index eeccc953187..43f4190c761 100644 --- a/mysql-test/suite/galera/t/galera_log_output_csv.test +++ b/mysql-test/suite/galera/t/galera_log_output_csv.test @@ -12,13 +12,17 @@ INSERT INTO t1 VALUES (1); SELECT COUNT(*) > 0 FROM mysql.general_log; +--disable_ps2_protocol SELECT 1 = 1 FROM t1; SELECT COUNT(*) = 1 FROM mysql.slow_log WHERE sql_text = 'SELECT 1 = 1 FROM t1'; +--enable_ps2_protocol --connection node_2 +--disable_ps2_protocol SELECT 2 = 2 FROM t1; SELECT COUNT(*) = 1 FROM mysql.slow_log WHERE sql_text = 'SELECT 2 = 2 FROM t1'; +--enable_ps2_protocol --connection node_1 DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_query_cache.test b/mysql-test/suite/galera/t/galera_query_cache.test index 900faba0e1b..ec7306e0188 100644 --- a/mysql-test/suite/galera/t/galera_query_cache.test +++ b/mysql-test/suite/galera/t/galera_query_cache.test @@ -2,6 +2,8 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +--disable_ps2_protocol + # # Ensure that the query cache behaves properly with respect to Galera # @@ -65,3 +67,4 @@ SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_ DROP TABLE t1; +--enable_ps2_protocol diff --git a/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test b/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test index 6d1e21fd94d..9a4b734e1d2 100644 --- a/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test +++ b/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test @@ -4,6 +4,8 @@ --source include/have_query_cache.inc --source include/galera_have_debug_sync.inc +--disable_ps2_protocol + CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); @@ -88,3 +90,5 @@ DROP TABLE t1; --connection node_2a SET DEBUG_SYNC = "RESET"; + +--enable_ps2_protocol diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test index b8d46db74f1..ba85aa5291c 100644 --- a/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test @@ -1,5 +1,7 @@ --source include/galera_cluster.inc +--disable_ps2_protocol + --connection node_2 CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; @@ -45,3 +47,6 @@ CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); --connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 --connection node_3 --source include/galera_wait_ready.inc + + +--enable_ps2_protocol diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test index 27674148f46..18e1f0023c3 100644 --- a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test @@ -1,6 +1,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +--disable_ps2_protocol # # Test the effect of gmcast.isolate on master during an SR transaction # @@ -133,3 +134,4 @@ CALL mtr.add_suppression("failed to send SR rollback for"); DROP TABLE t1; --source ../galera/include/auto_increment_offset_restore.inc +--enable_ps2_protocol diff --git a/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test index 63278555723..d08cab494b7 100644 --- a/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test +++ b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test @@ -6,6 +6,8 @@ --source include/have_innodb.inc --source include/big_test.inc +--disable_ps2_protocol + CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); @@ -56,3 +58,4 @@ CALL mtr.add_suppression('InnoDB: Resizing redo log from'); CALL mtr.add_suppression('InnoDB: Starting to delete and rewrite log files'); CALL mtr.add_suppression('InnoDB: New log files created, LSN='); +--enable_ps2_protocol diff --git a/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test b/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test index 9b8dae9d8e3..7a6c1bea4fb 100644 --- a/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test +++ b/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test @@ -6,6 +6,8 @@ --source include/have_innodb.inc --source include/big_test.inc +--disable_ps2_protocol + CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); @@ -51,3 +53,5 @@ SELECT COUNT(*) = 0 FROM t1; DROP TABLE ten; DROP TABLE t1; + +--enable_ps2_protocol From 9f40f02a8dda7f2becdc6e752557559e7835546d Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 22 Dec 2023 17:55:30 +0100 Subject: [PATCH 30/38] Fix galera.galera_kill_ddl test errors in debug mode. Marko reported DBUG_ASSERT from dict_stats_shutdown(). destroy_background_thd() does not like when current_thd is set. In galera, it can be the case, dict_stats_shutdown() can be called from user thread, to stop and later restart stats recalculations. --- storage/innobase/dict/dict0stats_bg.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 54378951b19..b0c34dc6d30 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -69,6 +69,8 @@ static recalc_pool_t recalc_pool; /** Whether the global data structures have been initialized */ static bool stats_initialised; +static THD *dict_stats_thd; + /*****************************************************************//** Free the resources occupied by the recalc pool, called once during thread de-initialization. */ @@ -90,6 +92,9 @@ static void dict_stats_recalc_pool_deinit() defrag_pool_t defrag_empty_pool; recalc_pool.swap(recalc_empty_pool); defrag_pool.swap(defrag_empty_pool); + + if (dict_stats_thd) + destroy_background_thd(dict_stats_thd); } /*****************************************************************//** @@ -379,7 +384,6 @@ static bool is_recalc_pool_empty() } static tpool::timer* dict_stats_timer; -static THD *dict_stats_thd; static void dict_stats_func(void*) { if (!dict_stats_thd) @@ -419,10 +423,4 @@ void dict_stats_shutdown() { delete dict_stats_timer; dict_stats_timer= 0; - - if (dict_stats_thd) - { - destroy_background_thd(dict_stats_thd); - dict_stats_thd= 0; - } } From 1b747ffd05dd524f8d43b35a2b583dc4c00d767b Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Sat, 23 Dec 2023 09:13:07 +0100 Subject: [PATCH 31/38] MDEV-33115 Update HeidiSQL to 12.6 --- win/packaging/heidisql.cmake | 2 +- win/packaging/heidisql.wxi.in | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/win/packaging/heidisql.cmake b/win/packaging/heidisql.cmake index 45a407371ba..681a4250e65 100644 --- a/win/packaging/heidisql.cmake +++ b/win/packaging/heidisql.cmake @@ -1,4 +1,4 @@ -SET(HEIDISQL_BASE_NAME "HeidiSQL_12.3_32_Portable") +SET(HEIDISQL_BASE_NAME "HeidiSQL_12.6_32_Portable") SET(HEIDISQL_ZIP "${HEIDISQL_BASE_NAME}.zip") SET(HEIDISQL_URL "http://www.heidisql.com/downloads/releases/${HEIDISQL_ZIP}") SET(HEIDISQL_DOWNLOAD_DIR ${THIRD_PARTY_DOWNLOAD_LOCATION}/${HEIDISQL_BASE_NAME}) diff --git a/win/packaging/heidisql.wxi.in b/win/packaging/heidisql.wxi.in index 03d5b579651..45bd6c4b218 100644 --- a/win/packaging/heidisql.wxi.in +++ b/win/packaging/heidisql.wxi.in @@ -68,6 +68,12 @@ + + + + + + @@ -115,6 +121,8 @@ + + From 371bf4abc61fffd86a3f87a90cb89179f4df3bee Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 23 Aug 2023 12:25:24 +0400 Subject: [PATCH 32/38] A 11.3->10.4 backport for MDEV-31991 Split class Database_qualified_name This is a requirement step to fix and merge easier MDEV-33019 The database part is not case sensitive in SP names The original MDEV-31991 commit commend: - Moving some of Database_qualified_name methods into a new class Identifier_chain2. - Changing the data type of the following variables from Database_qualified_name to Identifier_chain2: * q_pkg_proc in LEX::call_statement_start() * q_pkg_func in LEX::make_item_func_call_generic() Rationale: The data type of Database_qualified_name::m_db will be changed to Lex_ident_db soon. So Database_qualified_name won't be able to store the `pkg.routine` part of `db.pkg.routine` any more, because `pkg` must not depend on lower-case-table-names. --- sql/item.cc | 8 ++--- sql/sql_class.h | 88 ++++++++++++++++++++++++++++++++----------------- sql/sql_lex.cc | 4 +-- 3 files changed, 64 insertions(+), 36 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 259c4bf8f4d..21190b38e1a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2710,11 +2710,11 @@ Item_sp::func_name(THD *thd, bool is_package_function) const quoted `pkg` and `func` separately, so the entire result looks like: `db`.`pkg`.`func` */ - Database_qualified_name tmp= Database_qualified_name::split(m_name->m_name); - DBUG_ASSERT(tmp.m_db.length); - append_identifier(thd, &qname, &tmp.m_db); + Identifier_chain2 tmp= Identifier_chain2::split(m_name->m_name); + DBUG_ASSERT(tmp[0].length); + append_identifier(thd, &qname, &tmp[0]); qname.append('.'); - append_identifier(thd, &qname, &tmp.m_name); + append_identifier(thd, &qname, &tmp[1]); } else append_identifier(thd, &qname, &m_name->m_name); diff --git a/sql/sql_class.h b/sql/sql_class.h index fa124d899dd..2c6cc96a134 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -7051,6 +7051,61 @@ public: }; +class Identifier_chain2 +{ + LEX_CSTRING m_name[2]; +public: + Identifier_chain2() + :m_name{Lex_cstring(), Lex_cstring()} + { } + Identifier_chain2(const LEX_CSTRING &a, const LEX_CSTRING &b) + :m_name{a, b} + { } + + const LEX_CSTRING& operator [] (size_t i) const + { + return m_name[i]; + } + + static Identifier_chain2 split(const LEX_CSTRING &txt) + { + DBUG_ASSERT(txt.str[txt.length] == '\0'); // Expect 0-terminated input + const char *dot= strchr(txt.str, '.'); + if (!dot) + return Identifier_chain2(Lex_cstring(), txt); + size_t length0= dot - txt.str; + Lex_cstring name0(txt.str, length0); + Lex_cstring name1(txt.str + length0 + 1, txt.length - length0 - 1); + return Identifier_chain2(name0, name1); + } + + // Export as a qualified name string: 'db.name' + size_t make_qname(char *dst, size_t dstlen) const + { + return my_snprintf(dst, dstlen, "%.*s.%.*s", + (int) m_name[0].length, m_name[0].str, + (int) m_name[1].length, m_name[1].str); + } + + // Export as a qualified name string, allocate on mem_root. + bool make_qname(MEM_ROOT *mem_root, LEX_CSTRING *dst) const + { + const uint dot= !!m_name[0].length; + char *tmp; + /* format: [pkg + dot] + name + '\0' */ + dst->length= m_name[0].length + dot + m_name[1].length; + if (unlikely(!(dst->str= tmp= (char*) alloc_root(mem_root, + dst->length + 1)))) + return true; + snprintf(tmp, dst->length + 1, "%.*s%.*s%.*s", + (int) m_name[0].length, (m_name[0].length ? m_name[0].str : ""), + dot, ".", + (int) m_name[1].length, m_name[1].str); + return false; + } +}; + + /** This class resembles the SQL Standard schema qualified object name: ::= [ ] @@ -7093,41 +7148,16 @@ public: void copy(MEM_ROOT *mem_root, const LEX_CSTRING &db, const LEX_CSTRING &name); - static Database_qualified_name split(const LEX_CSTRING &txt) - { - DBUG_ASSERT(txt.str[txt.length] == '\0'); // Expect 0-terminated input - const char *dot= strchr(txt.str, '.'); - if (!dot) - return Database_qualified_name(NULL, 0, txt.str, txt.length); - size_t dblen= dot - txt.str; - Lex_cstring db(txt.str, dblen); - Lex_cstring name(txt.str + dblen + 1, txt.length - dblen - 1); - return Database_qualified_name(db, name); - } - // Export db and name as a qualified name string: 'db.name' size_t make_qname(char *dst, size_t dstlen) const { - return my_snprintf(dst, dstlen, "%.*s.%.*s", - (int) m_db.length, m_db.str, - (int) m_name.length, m_name.str); + return Identifier_chain2(m_db, m_name).make_qname(dst, dstlen); } // Export db and name as a qualified name string, allocate on mem_root. bool make_qname(MEM_ROOT *mem_root, LEX_CSTRING *dst) const { - const uint dot= !!m_db.length; - char *tmp; - /* format: [database + dot] + name + '\0' */ - dst->length= m_db.length + dot + m_name.length; - if (unlikely(!(dst->str= tmp= (char*) alloc_root(mem_root, - dst->length + 1)))) - return true; - snprintf(tmp, dst->length + 1, "%.*s%.*s%.*s", - (int) m_db.length, (m_db.length ? m_db.str : ""), - dot, ".", - (int) m_name.length, m_name.str); DBUG_SLOW_ASSERT(ok_for_lower_case_names(m_db.str)); - return false; + return Identifier_chain2(m_db, m_name).make_qname(mem_root, dst); } bool make_package_routine_name(MEM_ROOT *mem_root, @@ -7138,9 +7168,7 @@ public: size_t length= package.length + 1 + routine.length + 1; if (unlikely(!(tmp= (char *) alloc_root(mem_root, length)))) return true; - m_name.length= my_snprintf(tmp, length, "%.*s.%.*s", - (int) package.length, package.str, - (int) routine.length, routine.str); + m_name.length= Identifier_chain2(package, routine).make_qname(tmp, length); m_name.str= tmp; return false; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 127691997b0..4efa30c73c2 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -8616,7 +8616,7 @@ bool LEX::call_statement_start(THD *thd, const LEX_CSTRING &db, const LEX_CSTRING &proc) { Database_qualified_name q_db_pkg(db, pkg); - Database_qualified_name q_pkg_proc(pkg, proc); + Identifier_chain2 q_pkg_proc(pkg, proc); sp_name *spname; sql_command= SQLCOM_CALL; @@ -9026,7 +9026,7 @@ Item *LEX::make_item_func_call_generic(THD *thd, static Lex_cstring dot(".", 1); Lex_ident_sys db(thd, cdb), pkg(thd, cpkg), func(thd, cfunc); Database_qualified_name q_db_pkg(db, pkg); - Database_qualified_name q_pkg_func(pkg, func); + Identifier_chain2 q_pkg_func(pkg, func); sp_name *qname; if (db.is_null() || pkg.is_null() || func.is_null()) From 916caac2a52fd376bfb3b67d28a27c21f9d287e3 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 27 Dec 2023 13:22:49 +0400 Subject: [PATCH 33/38] MDEV-33019 The database part is not case sensitive in SP names Part#1 A non-functional change Changing the signature of Identifier_chain2::make_qname() from bool make_qname(MEM_ROOT *mem_root, LEX_CSTRING *dst) const; to LEX_CSTRING make_qname(MEM_ROOT *mem_root) const; Now the result is returned as LEX_CSTRING from the function rather than is passed as a parameter. The return value {NULL,0} means "EOM". --- sql/sql_class.h | 29 +++++++++++++++-------------- sql/sql_lex.cc | 10 ++++++---- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/sql/sql_class.h b/sql/sql_class.h index 2c6cc96a134..f8c8463265e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -7088,20 +7088,21 @@ public: } // Export as a qualified name string, allocate on mem_root. - bool make_qname(MEM_ROOT *mem_root, LEX_CSTRING *dst) const + LEX_CSTRING make_qname(MEM_ROOT *mem_root) const { - const uint dot= !!m_name[0].length; - char *tmp; + LEX_STRING dst; /* format: [pkg + dot] + name + '\0' */ - dst->length= m_name[0].length + dot + m_name[1].length; - if (unlikely(!(dst->str= tmp= (char*) alloc_root(mem_root, - dst->length + 1)))) - return true; - snprintf(tmp, dst->length + 1, "%.*s%.*s%.*s", - (int) m_name[0].length, (m_name[0].length ? m_name[0].str : ""), - dot, ".", - (int) m_name[1].length, m_name[1].str); - return false; + size_t dst_size= m_name[0].length + 1 /*dot*/ + m_name[1].length + 1/*\0*/; + if (unlikely(!(dst.str= (char*) alloc_root(mem_root, dst_size)))) + return {NULL, 0}; + if (!m_name[0].length) + { + dst.length= my_snprintf(dst.str, dst_size, "%.*s", + (int) m_name[1].length, m_name[1].str); + return {dst.str, dst.length}; + } + dst.length= make_qname(dst.str, dst_size); + return {dst.str, dst.length}; } }; @@ -7154,10 +7155,10 @@ public: return Identifier_chain2(m_db, m_name).make_qname(dst, dstlen); } // Export db and name as a qualified name string, allocate on mem_root. - bool make_qname(MEM_ROOT *mem_root, LEX_CSTRING *dst) const + LEX_CSTRING make_qname(MEM_ROOT *mem_root) const { DBUG_SLOW_ASSERT(ok_for_lower_case_names(m_db.str)); - return Identifier_chain2(m_db, m_name).make_qname(mem_root, dst); + return Identifier_chain2(m_db, m_name).make_qname(mem_root); } bool make_package_routine_name(MEM_ROOT *mem_root, diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 4efa30c73c2..21abdc290ee 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -6754,7 +6754,8 @@ sp_head *LEX::make_sp_head(THD *thd, const sp_name *name, name->m_name); else sp->init_sp_name(name); - sp->make_qname(sp->get_main_mem_root(), &sp->m_qname); + if (!(sp->m_qname= sp->make_qname(sp->get_main_mem_root())).str) + return NULL; } sphead= sp; } @@ -8632,7 +8633,7 @@ bool LEX::call_statement_start(THD *thd, const LEX_CSTRING &db, // Concat `pkg` and `name` to `pkg.name` LEX_CSTRING pkg_dot_proc; - if (q_pkg_proc.make_qname(thd->mem_root, &pkg_dot_proc) || + if (!(pkg_dot_proc= q_pkg_proc.make_qname(thd->mem_root)).str || check_ident_length(&pkg_dot_proc) || !(spname= new (thd->mem_root) sp_name(&db, &pkg_dot_proc, true))) return true; @@ -8698,7 +8699,8 @@ sp_package *LEX::create_package_start(THD *thd, return NULL; pkg->reset_thd_mem_root(thd); pkg->init(this); - pkg->make_qname(pkg->get_main_mem_root(), &pkg->m_qname); + if (!(pkg->m_qname= pkg->make_qname(pkg->get_main_mem_root())).str) + return NULL; sphead= pkg; return pkg; } @@ -9043,7 +9045,7 @@ Item *LEX::make_item_func_call_generic(THD *thd, // Concat `pkg` and `name` to `pkg.name` LEX_CSTRING pkg_dot_func; - if (q_pkg_func.make_qname(thd->mem_root, &pkg_dot_func) || + if (!(pkg_dot_func= q_pkg_func.make_qname(thd->mem_root)).str || check_ident_length(&pkg_dot_func) || !(qname= new (thd->mem_root) sp_name(&db, &pkg_dot_func, true))) return NULL; From 9695974e4b212aa4820e0ccfeb164f5444c0d58e Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 27 Dec 2023 13:41:42 +0400 Subject: [PATCH 34/38] MDEV-33019 The database part is not case sensitive in SP names Problem: sp_cache erroneously looked up fully qualified SP names (e.g. `DB`.`SP`), in case insensitive style. It was wrong, because only the "name" part is always case insensitive, while the "db" part should be compared according to lower_case_table_names (case sensitively for 0, case insensitively for 1 and 2). Fix: Adding a "casedn_name" parameter make_qname() to tell if the name part should be lower cased: `DB1`.`SP` -> "DB1.SP" (when casedn_name=false) `DB1`.`SP` -> "DB1.sp" (when casedn_name=true) and using make_qname() with casedn_name=true when creating sp_cache hash lookup keys. Details: As a result, it now works as follows: - sp_head::m_db is converted to lower case if lower_case_table_names>0 during the sp_name initialization phase. So when make_qname() is called, sp_head::m_db is already normalized. There are no changes in here. - The initialization phase of sp_head when creating sp_head::m_qname now calls make_qname() with casedn_name=true, so sp_head::m_name gets written to sp_head::m_qname in lower case. - sp_cache_lookup() now also calls make_qname() with casedn_name=true, so sp_head::m_name gets written to the temporary lookup key in lower case. - sp_cache::m_hashtable now uses case sensitive comparison --- mysql-test/main/lowercase_table5.result | 36 +++++++++++++++++++++++++ mysql-test/main/lowercase_table5.test | 31 +++++++++++++++++++++ sql/sp_cache.cc | 4 +-- sql/sql_class.h | 29 +++++++++++--------- sql/sql_lex.cc | 8 +++--- 5 files changed, 90 insertions(+), 18 deletions(-) diff --git a/mysql-test/main/lowercase_table5.result b/mysql-test/main/lowercase_table5.result index 7704e1fa658..7e78f71b75f 100644 --- a/mysql-test/main/lowercase_table5.result +++ b/mysql-test/main/lowercase_table5.result @@ -11,3 +11,39 @@ Database Create Database mysql_TEST CREATE DATABASE `mysql_TEST` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci */ DROP DATABASE mysql_test; DROP DATABASE mysql_TEST; +# +# Start of 10.4 tests +# +# +# MDEV-33019 The database part is not case sensitive in SP names +# +CREATE DATABASE DB1; +CREATE DATABASE db1; +CREATE PROCEDURE DB1.sp() SELECT 'This is DB1.sp' AS ret; +CREATE PROCEDURE db1.sp() SELECT 'This is db1.sp' AS ret; +CALL DB1.sp(); +ret +This is DB1.sp +CALL db1.sp(); +ret +This is db1.sp +DROP DATABASE DB1; +CALL DB1.sp(); +ERROR 42000: PROCEDURE DB1.sp does not exist +CALL db1.sp(); +ret +This is db1.sp +DROP DATABASE db1; +CREATE PROCEDURE SP() SELECT 'This is SP' AS ret; +CREATE PROCEDURE sp() SELECT 'This is sp' AS ret; +ERROR 42000: PROCEDURE sp already exists +CALL SP(); +ret +This is SP +CALL sp(); +ret +This is SP +DROP PROCEDURE SP; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/lowercase_table5.test b/mysql-test/main/lowercase_table5.test index dfdfafcb3da..0103dbf5fd2 100644 --- a/mysql-test/main/lowercase_table5.test +++ b/mysql-test/main/lowercase_table5.test @@ -18,3 +18,34 @@ DROP DATABASE mysql_test; DROP DATABASE mysql_TEST; # End of 10.0 tests + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-33019 The database part is not case sensitive in SP names +--echo # + +CREATE DATABASE DB1; +CREATE DATABASE db1; +CREATE PROCEDURE DB1.sp() SELECT 'This is DB1.sp' AS ret; +CREATE PROCEDURE db1.sp() SELECT 'This is db1.sp' AS ret; +CALL DB1.sp(); +CALL db1.sp(); +DROP DATABASE DB1; +--error ER_SP_DOES_NOT_EXIST +CALL DB1.sp(); +CALL db1.sp(); +DROP DATABASE db1; + +CREATE PROCEDURE SP() SELECT 'This is SP' AS ret; +--error ER_SP_ALREADY_EXISTS +CREATE PROCEDURE sp() SELECT 'This is sp' AS ret; +CALL SP(); +CALL sp(); +DROP PROCEDURE SP; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index e97f24c5487..cfdfea9ae0a 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -195,7 +195,7 @@ sp_head *sp_cache_lookup(sp_cache **cp, const Database_qualified_name *name) sp_cache *c= *cp; if (! c) return NULL; - return c->lookup(buf, name->make_qname(buf, sizeof(buf))); + return c->lookup(buf, name->make_qname(buf, sizeof(buf), true)); } @@ -302,7 +302,7 @@ sp_cache::~sp_cache() void sp_cache::init() { - my_hash_init(&m_hashtable, system_charset_info, 0, 0, 0, + my_hash_init(&m_hashtable, &my_charset_bin, 0, 0, 0, hash_get_key_for_sp_head, hash_free_sp_head, 0); } diff --git a/sql/sql_class.h b/sql/sql_class.h index f8c8463265e..e849b21b95b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -7080,15 +7080,18 @@ public: } // Export as a qualified name string: 'db.name' - size_t make_qname(char *dst, size_t dstlen) const + size_t make_qname(char *dst, size_t dstlen, bool casedn_part1) const { - return my_snprintf(dst, dstlen, "%.*s.%.*s", - (int) m_name[0].length, m_name[0].str, - (int) m_name[1].length, m_name[1].str); + size_t res= my_snprintf(dst, dstlen, "%.*s.%.*s", + (int) m_name[0].length, m_name[0].str, + (int) m_name[1].length, m_name[1].str); + if (casedn_part1 && dstlen > m_name[0].length) + my_casedn_str(system_charset_info, dst + m_name[0].length + 1); + return res; } // Export as a qualified name string, allocate on mem_root. - LEX_CSTRING make_qname(MEM_ROOT *mem_root) const + LEX_CSTRING make_qname(MEM_ROOT *mem_root, bool casedn_part1) const { LEX_STRING dst; /* format: [pkg + dot] + name + '\0' */ @@ -7097,11 +7100,12 @@ public: return {NULL, 0}; if (!m_name[0].length) { + DBUG_ASSERT(!casedn_part1); // Should not be called this way dst.length= my_snprintf(dst.str, dst_size, "%.*s", (int) m_name[1].length, m_name[1].str); return {dst.str, dst.length}; } - dst.length= make_qname(dst.str, dst_size); + dst.length= make_qname(dst.str, dst_size, casedn_part1); return {dst.str, dst.length}; } }; @@ -7150,15 +7154,15 @@ public: const LEX_CSTRING &name); // Export db and name as a qualified name string: 'db.name' - size_t make_qname(char *dst, size_t dstlen) const + size_t make_qname(char *dst, size_t dstlen, bool casedn_name) const { - return Identifier_chain2(m_db, m_name).make_qname(dst, dstlen); + return Identifier_chain2(m_db, m_name).make_qname(dst, dstlen, casedn_name); } // Export db and name as a qualified name string, allocate on mem_root. - LEX_CSTRING make_qname(MEM_ROOT *mem_root) const + LEX_CSTRING make_qname(MEM_ROOT *mem_root, bool casedn_name) const { DBUG_SLOW_ASSERT(ok_for_lower_case_names(m_db.str)); - return Identifier_chain2(m_db, m_name).make_qname(mem_root); + return Identifier_chain2(m_db, m_name).make_qname(mem_root, casedn_name); } bool make_package_routine_name(MEM_ROOT *mem_root, @@ -7169,7 +7173,8 @@ public: size_t length= package.length + 1 + routine.length + 1; if (unlikely(!(tmp= (char *) alloc_root(mem_root, length)))) return true; - m_name.length= Identifier_chain2(package, routine).make_qname(tmp, length); + m_name.length= Identifier_chain2(package, routine).make_qname(tmp, length, + false); m_name.str= tmp; return false; } @@ -7198,7 +7203,7 @@ public: { } const char *ptr() const { - m_name->make_qname(err_buffer, sizeof(err_buffer)); + m_name->make_qname(err_buffer, sizeof(err_buffer), false); return err_buffer; } }; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 21abdc290ee..847bd1d72d2 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -6754,7 +6754,7 @@ sp_head *LEX::make_sp_head(THD *thd, const sp_name *name, name->m_name); else sp->init_sp_name(name); - if (!(sp->m_qname= sp->make_qname(sp->get_main_mem_root())).str) + if (!(sp->m_qname= sp->make_qname(sp->get_main_mem_root(), true)).str) return NULL; } sphead= sp; @@ -8633,7 +8633,7 @@ bool LEX::call_statement_start(THD *thd, const LEX_CSTRING &db, // Concat `pkg` and `name` to `pkg.name` LEX_CSTRING pkg_dot_proc; - if (!(pkg_dot_proc= q_pkg_proc.make_qname(thd->mem_root)).str || + if (!(pkg_dot_proc= q_pkg_proc.make_qname(thd->mem_root, false)).str || check_ident_length(&pkg_dot_proc) || !(spname= new (thd->mem_root) sp_name(&db, &pkg_dot_proc, true))) return true; @@ -8699,7 +8699,7 @@ sp_package *LEX::create_package_start(THD *thd, return NULL; pkg->reset_thd_mem_root(thd); pkg->init(this); - if (!(pkg->m_qname= pkg->make_qname(pkg->get_main_mem_root())).str) + if (!(pkg->m_qname= pkg->make_qname(pkg->get_main_mem_root(), true)).str) return NULL; sphead= pkg; return pkg; @@ -9045,7 +9045,7 @@ Item *LEX::make_item_func_call_generic(THD *thd, // Concat `pkg` and `name` to `pkg.name` LEX_CSTRING pkg_dot_func; - if (!(pkg_dot_func= q_pkg_func.make_qname(thd->mem_root)).str || + if (!(pkg_dot_func= q_pkg_func.make_qname(thd->mem_root, false)).str || check_ident_length(&pkg_dot_func) || !(qname= new (thd->mem_root) sp_name(&db, &pkg_dot_func, true))) return NULL; From 832e96deb6f368591dcb35a4fa33b2fd770aa17a Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 15 Dec 2023 11:00:15 -0800 Subject: [PATCH 35/38] MDEV-29362 Crash with query using constant subquery as left part of IN subquery If a query has a HAVING clause that contains a predicate with a constant IN subquery whose lef part in its turn is a subquery and the predicate is subject to pushdown from HAVING to WHERE then execution of the query could cause a crash of the server. The cause of the problem was the missing implementation of the walk() method for the class Item_in_optimizer. As a result in some cases the left operand of the Item_in_optimizer condition could be traversed twice by the walk procedure. For many call-back functions used as an argument of this procedure it does not matter. Yet it matters for the call-back function cleanup_excluding_immutables_processor() used in pushdown of predicates from HAVING to WHERE. If the processed item is marked with the IMMUTABLE_FL flag then the processor just removes this flag, otherwise it performs cleanup of the item making it unfixed. If an item is marked with an the IMMUTABLE_FL and it traversed with this processor twice then it becomes unfixed after the second traversal though the flag indicates that the item should not be cleaned up. Approved by Oleksandr Byelkin --- mysql-test/main/subselect4.result | 79 +++++++++++++++++++++++++++++++ mysql-test/main/subselect4.test | 36 ++++++++++++++ sql/item_cmpfunc.cc | 17 +++++++ sql/item_cmpfunc.h | 1 + 4 files changed, 133 insertions(+) diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result index 9f435146e0b..4edcffa0ee5 100644 --- a/mysql-test/main/subselect4.result +++ b/mysql-test/main/subselect4.result @@ -3213,4 +3213,83 @@ FROM x ) ); ERROR 21000: Operand should contain 2 column(s) +# +# MDEV-29362: Constant subquery used as left part of IN subquery +# +CREATE TABLE t1 (a int) ENGINE=MyISAM; +INSERT INTO t1 VALUES (15), (1), (2); +CREATE TABLE t2 (b int) ENGINE=MyISAM; +INSERT INTO t2 VALUES (15), (1); +CREATE TABLE t3 (c int) ENGINE=MyISAM; +INSERT INTO t3 VALUES (15), (1); +SET optimizer_switch='condition_pushdown_from_having=off'; +SELECT a FROM t1 GROUP BY a +HAVING a = ( (SELECT b FROM t2 where b=1) IN (SELECT c FROM t3) ) + 1; +a +2 +SELECT a FROM t1 GROUP BY a +HAVING a IN ( (SELECT b FROM t2 where b=1) IN (SELECT c FROM t3) ); +a +1 +SET optimizer_switch='condition_pushdown_from_having=on'; +SELECT a FROM t1 GROUP BY a +HAVING a = ( (SELECT b FROM t2 where b=1) IN (SELECT c FROM t3) ) + 1; +a +2 +SELECT a FROM t1 GROUP BY a +HAVING a IN ( (SELECT b FROM t2 where b=1) IN (SELECT c FROM t3) ); +a +1 +EXPLAIN FORMAT=JSON SELECT a FROM t1 GROUP BY a +HAVING a = ( (SELECT b FROM t2 where b=1) IN (SELECT c FROM t3) ) + 1; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 3, + "filtered": 100, + "attached_condition": "t1.a = (((subquery#2),(subquery#3)) + 1)" + }, + "subqueries": [ + { + "query_block": { + "select_id": 3, + "having_condition": "trigcond(t3.c is null)", + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows": 2, + "filtered": 100, + "attached_condition": "trigcond(1 = t3.c or t3.c is null)" + } + } + }, + { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 2, + "filtered": 100, + "attached_condition": "t2.b = 1" + } + } + } + ] + } +} +PREPARE stmt FROM "SELECT a FROM t1 GROUP BY a +HAVING a = ( (SELECT b FROM t2 where b=1) IN (SELECT c FROM t3) ) + 1"; +EXECUTE stmt; +a +2 +EXECUTE stmt; +a +2 +DEALLOCATE PREPARE stmt; +DROP TABLE t1,t2,t3; # End of 10.4 tests diff --git a/mysql-test/main/subselect4.test b/mysql-test/main/subselect4.test index 23611e4ec0d..d5871f1202c 100644 --- a/mysql-test/main/subselect4.test +++ b/mysql-test/main/subselect4.test @@ -2629,5 +2629,41 @@ SELECT ) ); +--echo # +--echo # MDEV-29362: Constant subquery used as left part of IN subquery +--echo # + +CREATE TABLE t1 (a int) ENGINE=MyISAM; +INSERT INTO t1 VALUES (15), (1), (2); +CREATE TABLE t2 (b int) ENGINE=MyISAM; +INSERT INTO t2 VALUES (15), (1); +CREATE TABLE t3 (c int) ENGINE=MyISAM; +INSERT INTO t3 VALUES (15), (1); + +let $q1= +SELECT a FROM t1 GROUP BY a + HAVING a = ( (SELECT b FROM t2 where b=1) IN (SELECT c FROM t3) ) + 1; +let $q2= +SELECT a FROM t1 GROUP BY a + HAVING a IN ( (SELECT b FROM t2 where b=1) IN (SELECT c FROM t3) ); + +SET optimizer_switch='condition_pushdown_from_having=off'; + +eval $q1; +eval $q2; + +SET optimizer_switch='condition_pushdown_from_having=on'; + +eval $q1; +eval $q2; + +eval EXPLAIN FORMAT=JSON $q1; + +eval PREPARE stmt FROM "$q1"; +EXECUTE stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +DROP TABLE t1,t2,t3; --echo # End of 10.4 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2a1fc3f90d3..cffd2e8add8 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1444,6 +1444,23 @@ bool Item_in_optimizer::invisible_mode() } +bool Item_in_optimizer::walk(Item_processor processor, + bool walk_subquery, + void *arg) +{ + bool res= FALSE; + if (args[1]->type() == Item::SUBSELECT_ITEM && + ((Item_subselect *)args[1])->substype() != Item_subselect::EXISTS_SUBS && + !(((Item_subselect *)args[1])->substype() == Item_subselect::IN_SUBS && + ((Item_in_subselect *)args[1])->test_strategy(SUBS_IN_TO_EXISTS))) + res= args[0]->walk(processor, walk_subquery, arg); + if (!res) + res= args[1]->walk(processor, walk_subquery, arg); + + return res || (this->*processor)(arg); +} + + /** Add an expression cache for this subquery if it is needed diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 9731eb7755d..1ae0e652e88 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -385,6 +385,7 @@ public: bool eval_not_null_tables(void *opt_arg); void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge); bool invisible_mode(); + bool walk(Item_processor processor, bool walk_subquery, void *arg); void reset_cache() { cache= NULL; } virtual void print(String *str, enum_query_type query_type); void restore_first_argument(); From 96130b1898d34222d1f0543d75dc1acb6cdb8b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 3 Jan 2024 08:52:50 +0200 Subject: [PATCH 36/38] MDEV-33157 WSREP: Fix function pointer mismatch wsrep_plugin_init(), wsrep_plugin_deinit(): Remove these dummy functions in order to fix an error that would be flagged by cmake -DWITH_UBSAN=ON when using clang. wsrep_show_ready(), wsrep_show_bf_aborts(): Correct the signature. --- sql/wsrep_mysqld.cc | 3 ++- sql/wsrep_mysqld.h | 3 ++- sql/wsrep_plugin.cc | 16 ++-------------- sql/wsrep_thd.cc | 2 +- sql/wsrep_thd.h | 2 +- 5 files changed, 8 insertions(+), 18 deletions(-) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 7c8bb683aab..5ec96478e4a 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -512,7 +512,8 @@ my_bool wsrep_ready_get (void) return ret; } -int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff) +int wsrep_show_ready(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type) { var->type= SHOW_MY_BOOL; var->value= buff; diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 921b75ae42d..62bab628e78 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -148,7 +148,8 @@ extern char* wsrep_cluster_capabilities; int wsrep_show_status(THD *thd, SHOW_VAR *var, void *buff, system_status_var *status_var, enum_var_type scope); -int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff); +int wsrep_show_ready(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum_var_type); void wsrep_free_status(THD *thd); void wsrep_update_cluster_state_uuid(const char* str); diff --git a/sql/wsrep_plugin.cc b/sql/wsrep_plugin.cc index 743b8a593b8..3fa5f7b7ef4 100644 --- a/sql/wsrep_plugin.cc +++ b/sql/wsrep_plugin.cc @@ -18,18 +18,6 @@ #include -static int wsrep_plugin_init(void *p) -{ - WSREP_DEBUG("wsrep_plugin_init()"); - return 0; -} - -static int wsrep_plugin_deinit(void *p) -{ - WSREP_DEBUG("wsrep_plugin_deinit()"); - return 0; -} - struct Mysql_replication wsrep_plugin= { MYSQL_REPLICATION_INTERFACE_VERSION }; @@ -42,8 +30,8 @@ maria_declare_plugin(wsrep) "Codership Oy", "Wsrep replication plugin", PLUGIN_LICENSE_GPL, - wsrep_plugin_init, - wsrep_plugin_deinit, + NULL, + NULL, 0x0100, NULL, /* Status variables */ NULL, /* System variables */ diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 4a6f0736c76..243a3ccdd3e 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -36,7 +36,7 @@ static Wsrep_thd_queue* wsrep_rollback_queue= 0; static Atomic_counter wsrep_bf_aborts_counter; -int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff, +int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, void *, system_status_var *, enum enum_var_type scope) { wsrep_local_bf_aborts= wsrep_bf_aborts_counter; diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 488268bde69..22596840296 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -82,7 +82,7 @@ private: mysql_cond_t COND_wsrep_thd_queue; }; -int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff, +int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, void *, system_status_var *, enum enum_var_type scope); bool wsrep_create_appliers(long threads, bool mutex_protected=false); void wsrep_create_rollbacker(); From 77b8bedf345384bb15f4b2ac53af3cea871f2df8 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 3 Jan 2024 15:08:22 +0530 Subject: [PATCH 37/38] MDEV-33098 The test innodb.doublewrite_debug occasionally fails to start up InnoDB - innodb.doublewrite_debug should avoid the checkpoint before killing the server. So used debug sync and innodb_flush_sync to avoid the checkpoint completely. Test case allowed to skip on MSAN builder due to extra checkpoint. --- .../suite/innodb/r/doublewrite_debug.result | 8 +++-- .../suite/innodb/t/doublewrite_debug.test | 30 +++++++++++++++---- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/innodb/r/doublewrite_debug.result b/mysql-test/suite/innodb/r/doublewrite_debug.result index 960610a7091..08d9a2a92e8 100644 --- a/mysql-test/suite/innodb/r/doublewrite_debug.result +++ b/mysql-test/suite/innodb/r/doublewrite_debug.result @@ -23,7 +23,7 @@ commit work; # Test Begin: Test if recovery works if 1st page and 2nd page # of system tablespace is full of zeroes. SET GLOBAL innodb_fast_shutdown = 0; -# restart +# restart: --debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0 begin; insert into t1 values (6, repeat('%', 400)); # Make the first page dirty for system tablespace @@ -33,6 +33,7 @@ set global innodb_fil_make_page_dirty_debug = 0; set global innodb_saved_page_number_debug = 1; set global innodb_fil_make_page_dirty_debug = 0; set global innodb_buf_flush_list_now = 1; +# Kill the server # Make the 1st page (page_no=0) and 2nd page (page_no=1) # of the system tablespace all zeroes. # restart @@ -52,7 +53,7 @@ f1 f2 # --------------------------------------------------------------- # Test Begin: Test if recovery works if 1st page of # system tablespace is corrupted and 2nd page as corrupted. -set global innodb_log_checkpoint_now = 1; +# restart: --debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0 begin; insert into t1 values (6, repeat('%', 400)); # Make the first page dirty for system tablespace @@ -62,6 +63,7 @@ set global innodb_fil_make_page_dirty_debug = 0; set global innodb_saved_page_number_debug = 1; set global innodb_fil_make_page_dirty_debug = 0; set global innodb_buf_flush_list_now = 1; +# Kill the server # Corrupt the 1st page (page_no=0) and 2nd page of the system tablespace. # restart FOUND 2 /InnoDB: Restoring page \[page id: space=0, page number=0\] of datafile/ in mysqld.1.err @@ -83,7 +85,7 @@ drop table t1; # MDEV-12600 crash during install_db with innodb_page_size=32K # and ibdata1=3M # -# restart: --innodb-log-group-home-dir=MYSQLTEST_VARDIR/tmp/doublewrite --innodb-data-home-dir=MYSQLTEST_VARDIR/tmp/doublewrite --innodb-data-file-path=ibdata1:1M;ibdata2:1M:autoextend +# restart: --innodb-log-group-home-dir=MYSQLTEST_VARDIR/tmp/doublewrite --innodb-data-home-dir=MYSQLTEST_VARDIR/tmp/doublewrite --innodb-undo-tablespaces=0 --innodb-data-file-path=ibdata1:1M;ibdata2:1M:autoextend SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); diff --git a/mysql-test/suite/innodb/t/doublewrite_debug.test b/mysql-test/suite/innodb/t/doublewrite_debug.test index 86809cc43c0..b8eb81c645c 100644 --- a/mysql-test/suite/innodb/t/doublewrite_debug.test +++ b/mysql-test/suite/innodb/t/doublewrite_debug.test @@ -44,7 +44,9 @@ commit work; # Slow shutdown and restart to make sure ibuf merge is finished SET GLOBAL innodb_fast_shutdown = 0; let $shutdown_timeout=; +let $restart_parameters="--debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0"; --source include/restart_mysqld.inc +--source ../include/no_checkpoint_start.inc begin; insert into t1 values (6, repeat('%', 400)); @@ -57,8 +59,20 @@ set global innodb_saved_page_number_debug = 1; set global innodb_fil_make_page_dirty_debug = 0; set global innodb_buf_flush_list_now = 1; -let $shutdown_timeout=0; ---source include/shutdown_mysqld.inc + +--let CLEANUP_IF_CHECKPOINT=drop table t1, unexpected_checkpoint; +# Occasionally, a checkpoint would occur on the MSAN builder. +# We do not know the reason, because the failure can only be reproduced if there is +# enough load in that environment. +# Therefore, we allow the test to be skipped when run on MSAN. +# In other environments, we want the test to fail if a checkpoint occurs, +# so that we would catch it if it starts to happen regularly. +if (`select count(*) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "MSAN%"`) +{ +--let CLEANUP_IF_CHECKPOINT=drop table t1; +} + +--source ../include/no_checkpoint_end.inc --echo # Make the 1st page (page_no=0) and 2nd page (page_no=1) --echo # of the system tablespace all zeroes. @@ -74,6 +88,7 @@ print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}); close FILE; EOF +let $restart_parameters=; --source include/start_mysqld.inc let SEARCH_PATTERN=InnoDB: Restoring page \[page id: space=0, page number=0\] of datafile; @@ -90,7 +105,9 @@ select f1, f2 from t1; --echo # Test Begin: Test if recovery works if 1st page of --echo # system tablespace is corrupted and 2nd page as corrupted. -set global innodb_log_checkpoint_now = 1; +let $restart_parameters="--debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0"; +--source include/restart_mysqld.inc +--source ../include/no_checkpoint_start.inc begin; insert into t1 values (6, repeat('%', 400)); @@ -103,8 +120,8 @@ set global innodb_saved_page_number_debug = 1; set global innodb_fil_make_page_dirty_debug = 0; set global innodb_buf_flush_list_now = 1; -let $shutdown_timeout=0; ---source include/shutdown_mysqld.inc + +--source ../include/no_checkpoint_end.inc --echo # Corrupt the 1st page (page_no=0) and 2nd page of the system tablespace. perl; @@ -119,6 +136,7 @@ print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}/2); close FILE; EOF +let $restart_parameters=; --source include/start_mysqld.inc let SEARCH_PATTERN=InnoDB: Restoring page \[page id: space=0, page number=0\] of datafile; @@ -145,7 +163,7 @@ WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); --let $ibp=--innodb-log-group-home-dir=$bugdir --innodb-data-home-dir=$bugdir ---let $ibd=$ibp --innodb-undo-tablespaces=0 +--let $ibp=$ibp --innodb-undo-tablespaces=0 --let $ibp=$ibp --innodb-data-file-path=ibdata1:1M;ibdata2:1M:autoextend --let $restart_parameters= $ibp From cc5c0eda4c1a516753de238e02a024b0f044b738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 3 Jan 2024 12:08:21 +0200 Subject: [PATCH 38/38] MDEV-33156 Crash on innodb_buf_flush_list_now=ON and innodb_force_recovery=6 srv_start(): Move a read only mode startup tweak from innodb_init_params() to the correct location. Also if innodb_force_recovery=6 we will disable the doublewrite buffer, because InnoDB must run in read-only mode to prevent further corruption. This change only affects debug checks. Whenever srv_read_only_mode holds, the buf_pool.flush_list will be empty, that is, there will be no writes of persistent InnoDB data pages. Reviewed by: Thirunarayanan Balathandayuthapani --- mysql-test/suite/innodb/r/ibuf_not_empty.result | 1 + mysql-test/suite/innodb/t/ibuf_not_empty.test | 1 + storage/innobase/handler/ha_innodb.cc | 5 ----- storage/innobase/srv/srv0start.cc | 8 ++++++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/innodb/r/ibuf_not_empty.result b/mysql-test/suite/innodb/r/ibuf_not_empty.result index f2da89990b0..f26ea7fb8c2 100644 --- a/mysql-test/suite/innodb/r/ibuf_not_empty.result +++ b/mysql-test/suite/innodb/r/ibuf_not_empty.result @@ -12,6 +12,7 @@ check table t1; Table Op Msg_type Msg_text test.t1 check Warning InnoDB: Index 'b' contains 990 entries, should be 1024. test.t1 check error Corrupt +SET GLOBAL innodb_buf_flush_list_now=ON; # restart SET GLOBAL innodb_fast_shutdown=0; # restart diff --git a/mysql-test/suite/innodb/t/ibuf_not_empty.test b/mysql-test/suite/innodb/t/ibuf_not_empty.test index 207427d9ab8..11606f2d925 100644 --- a/mysql-test/suite/innodb/t/ibuf_not_empty.test +++ b/mysql-test/suite/innodb/t/ibuf_not_empty.test @@ -72,6 +72,7 @@ EOF --replace_regex /contains \d+ entries/contains 990 entries/ check table t1; +SET GLOBAL innodb_buf_flush_list_now=ON; --source include/shutdown_mysqld.inc diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 026309d0ff6..777ea1ba86e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3893,11 +3893,6 @@ static int innodb_init_params() } #endif - if (srv_read_only_mode) { - ib::info() << "Started in read only mode"; - srv_use_doublewrite_buf = FALSE; - } - #ifdef LINUX_NATIVE_AIO #elif !defined _WIN32 /* Currently native AIO is supported only on windows and linux diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 6f40df82f8f..56e41616d1d 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1073,10 +1073,14 @@ dberr_t srv_start(bool create_new_db) if (srv_force_recovery) { ib::info() << "!!! innodb_force_recovery is set to " << srv_force_recovery << " !!!"; + if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) { + srv_read_only_mode = true; + } } - if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) { - srv_read_only_mode = true; + if (srv_read_only_mode) { + sql_print_information("InnoDB: Started in read only mode"); + srv_use_doublewrite_buf = false; } high_level_read_only = srv_read_only_mode