From 90c39c5a500278d19240550f7c4bf370c441c100 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 1 Feb 2023 20:20:57 +0100 Subject: hopefully the last case of walk-and-delete HASH antipattern here global_index_stats is expected to be big, so we don't restart the search, but use a two-pass approach --- sql/handler.cc | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'sql/handler.cc') diff --git a/sql/handler.cc b/sql/handler.cc index 42bfec6652f..d90522f0a13 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7233,11 +7233,13 @@ static int del_global_index_stats_for_table(THD *thd, uchar* cache_key, size_t cache_key_length) { int res = 0; + uint to_delete_counter= 0; + INDEX_STATS *index_stats_to_delete[MAX_INDEXES]; DBUG_ENTER("del_global_index_stats_for_table"); mysql_mutex_lock(&LOCK_global_index_stats); - for (uint i= 0; i < global_index_stats.records;) + for (uint i= 0; i < global_index_stats.records; i++) { INDEX_STATS *index_stats = (INDEX_STATS*) my_hash_element(&global_index_stats, i); @@ -7247,19 +7249,13 @@ int del_global_index_stats_for_table(THD *thd, uchar* cache_key, size_t cache_ke index_stats->index_name_length >= cache_key_length && !memcmp(index_stats->index, cache_key, cache_key_length)) { - res= my_hash_delete(&global_index_stats, (uchar*)index_stats); - /* - In our HASH implementation on deletion one elements - is moved into a place where a deleted element was, - and the last element is moved into the empty space. - Thus we need to re-examine the current element, but - we don't have to restart the search from the beginning. - */ + index_stats_to_delete[to_delete_counter++]= index_stats; } - else - i++; } + for (uint i= 0; i < to_delete_counter; i++) + res= my_hash_delete(&global_index_stats, (uchar*)index_stats_to_delete[i]); + mysql_mutex_unlock(&LOCK_global_index_stats); DBUG_RETURN(res); } -- cgit v1.2.1 From 965bdf3e66a9265345003c6e172aad7b1864e280 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 28 Feb 2023 10:49:25 +0400 Subject: MDEV-30746 Regression in ucs2_general_mysql500_ci 1. Adding a separate MY_COLLATION_HANDLER my_collation_ucs2_general_mysql500_ci_handler implementing a proper order for ucs2_general_mysql500_ci The problem happened because ucs2_general_mysql500_ci erroneously used my_collation_ucs2_general_ci_handler. 2. Cosmetic changes: Renaming: - plane00_mysql500 to my_unicase_mysql500_page00 - my_unicase_pages_mysql500 to my_unicase_mysql500_pages to use the same naming style with: - my_unicase_default_page00 - my_unicase_defaul_pages 3. Moving code fragments from - handler::check_collation_compatibility() in handler.cc - upgrade_collation() in table.cc into new methods in class Charset, to reuse the code easier. --- sql/handler.cc | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'sql/handler.cc') diff --git a/sql/handler.cc b/sql/handler.cc index d90522f0a13..8ed8ee64880 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4110,7 +4110,7 @@ int handler::check_collation_compatibility() { ulong mysql_version= table->s->mysql_version; - if (mysql_version < 50124) + if (mysql_version < Charset::latest_mariadb_version_with_collation_change()) { KEY *key= table->key_info; KEY *key_end= key + table->s->keys; @@ -4124,18 +4124,7 @@ int handler::check_collation_compatibility() continue; Field *field= table->field[key_part->fieldnr - 1]; uint cs_number= field->charset()->number; - if ((mysql_version < 50048 && - (cs_number == 11 || /* ascii_general_ci - bug #29499, bug #27562 */ - cs_number == 41 || /* latin7_general_ci - bug #29461 */ - cs_number == 42 || /* latin7_general_cs - bug #29461 */ - cs_number == 20 || /* latin7_estonian_cs - bug #29461 */ - cs_number == 21 || /* latin2_hungarian_ci - bug #29461 */ - cs_number == 22 || /* koi8u_general_ci - bug #29461 */ - cs_number == 23 || /* cp1251_ukrainian_ci - bug #29461 */ - cs_number == 26)) || /* cp1250_general_ci - bug #29461 */ - (mysql_version < 50124 && - (cs_number == 33 || /* utf8_general_ci - bug #27877 */ - cs_number == 35))) /* ucs2_general_ci - bug #27877 */ + if (Charset::collation_changed_order(mysql_version, cs_number)) return HA_ADMIN_NEEDS_UPGRADE; } } -- cgit v1.2.1 From f83b7ae13d9619af29d74a27dd253b67aa0ee4fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 6 Apr 2023 07:50:23 +0300 Subject: MDEV-26175 : Assertion `! thd->in_sub_stmt' failed in bool trans_rollback_stmt(THD*) If we are inside stored function or trigger we should not commit or rollback current statement transaction. Signed-off-by: Julius Goryavsky --- sql/handler.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'sql/handler.cc') diff --git a/sql/handler.cc b/sql/handler.cc index 8ed8ee64880..7eaaaf63f00 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -6618,7 +6618,13 @@ static int wsrep_after_row(THD *thd) wsrep_thd_is_local(thd) && thd->wsrep_affected_rows > wsrep_max_ws_rows) { - trans_rollback_stmt(thd) || trans_rollback(thd); + /* + If we are inside stored function or trigger we should not commit or + rollback current statement transaction. See comment in ha_commit_trans() + call for more information. + */ + if (!thd->in_sub_stmt) + trans_rollback_stmt(thd) || trans_rollback(thd); my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0)); DBUG_RETURN(ER_ERROR_DURING_COMMIT); } -- cgit v1.2.1 From 210db2935cb3802f6806ba3b23c32263611e3e2f Mon Sep 17 00:00:00 2001 From: Denis Protivensky Date: Tue, 14 Mar 2023 14:08:12 +0300 Subject: MDEV-30804 Rollback multi-engine transaction requiring 2PC but committing in one phase Signed-off-by: Julius Goryavsky --- sql/handler.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'sql/handler.cc') diff --git a/sql/handler.cc b/sql/handler.cc index 4afd30021ee..e0dd51376ad 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1733,7 +1733,19 @@ int ha_commit_trans(THD *thd, bool all) ordering is normally done. Commit ordering must be done here. */ if (run_wsrep_hooks) - error= wsrep_before_commit(thd, all); + { + // This commit involves more than one storage engine and requires + // two phases, but some engines don't support it. + // Issue a message to the client and roll back the transaction. + if (trans->no_2pc && rw_ha_count > 1) + { + my_message(ER_ERROR_DURING_COMMIT, "Transactional commit not supported " + "by involved engine(s)", MYF(0)); + error= 1; + } + else + error= wsrep_before_commit(thd, all); + } if (error) { ha_rollback_trans(thd, FALSE); -- cgit v1.2.1 From 31f09e36c183d026a28f42ddbb9be2229613a3ed Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Tue, 18 Apr 2023 13:22:43 -0600 Subject: MDEV-31038: Parallel Replication Breaks if XA PREPARE Fails Updating Slave GTID State If a replica failed to update the GTID slave state when committing an XA PREPARE, the replica would retry the transaction and get an out-of-order GTID error. This is because the commit phase of an XA PREPARE is bifurcated. That is, first, the prepare is handled by the relevant storage engines. Then second, the GTID slave state is updated as a separate autocommit transaction. If the second phase fails, and the transaction is retried, then the same transaction is attempted to be committed again, resulting in a GTID out-of-order error. This patch fixes this error by immediately stopping the slave and reporting the appropriate error. That is, there was logic to bypass the error when updating the GTID slave state table if the underlying error is allowed for retry on a parallel slave. This patch adds a parameter to disallow the error bypass, thereby forcing the error state to still happen. Reviewed By ============ Andrei Elkin --- sql/handler.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'sql/handler.cc') diff --git a/sql/handler.cc b/sql/handler.cc index 926ef2f4f54..eaaf4664c07 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2057,8 +2057,11 @@ int ha_rollback_trans(THD *thd, bool all) rollback without signalling following transactions. And in release builds, we explicitly do the signalling before rolling back. */ - DBUG_ASSERT(!(thd->rgi_slave && thd->rgi_slave->did_mark_start_commit) || - thd->transaction->xid_state.is_explicit_XA()); + DBUG_ASSERT( + !(thd->rgi_slave && thd->rgi_slave->did_mark_start_commit) || + (thd->transaction->xid_state.is_explicit_XA() || + (thd->rgi_slave->gtid_ev_flags2 & Gtid_log_event::FL_PREPARED_XA))); + if (thd->rgi_slave && thd->rgi_slave->did_mark_start_commit) thd->rgi_slave->unmark_start_commit(); } -- cgit v1.2.1