From e95f78f4752e4c0433e969f34e01b4b6be39efa1 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Wed, 16 Jun 2021 17:10:11 +0300 Subject: [PATCH] MDEV-21117 post-push to cover a "custom" xid format Due to wsrep uses its own xid format for its recovery, the xid hashing has to be refined. When a xid object is not in the server "mysql" format, the hash record made to contain the xid also in the full format. --- sql/handler.cc | 41 ++++++++++++++++++++++++++++------------- sql/handler.h | 6 ++++-- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 0ec8afde16e..393f6234653 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2399,15 +2399,22 @@ struct xarecover_st or NULL. */ static xid_recovery_member* -xid_member_insert(HASH *hash_arg, my_xid xid_arg, MEM_ROOT *ptr_mem_root) +xid_member_insert(HASH *hash_arg, my_xid xid_arg, MEM_ROOT *ptr_mem_root, + XID *full_xid_arg) { xid_recovery_member *member= (xid_recovery_member *) alloc_root(ptr_mem_root, sizeof(xid_recovery_member)); + XID *xid_full= NULL; - if (!member) + if (full_xid_arg) + xid_full= (XID*) alloc_root(ptr_mem_root, sizeof(XID)); + + if (!member || (full_xid_arg && !xid_full)) return NULL; - *member= xid_recovery_member(xid_arg, 1, false); + if (full_xid_arg) + *xid_full= *full_xid_arg; + *member= xid_recovery_member(xid_arg, 1, false, xid_full); return my_hash_insert(hash_arg, (uchar*) member) ? NULL : member; @@ -2421,14 +2428,15 @@ xid_member_insert(HASH *hash_arg, my_xid xid_arg, MEM_ROOT *ptr_mem_root) true otherwise. */ static bool xid_member_replace(HASH *hash_arg, my_xid xid_arg, - MEM_ROOT *ptr_mem_root) + MEM_ROOT *ptr_mem_root, + XID *full_xid_arg) { xid_recovery_member* member; if ((member= (xid_recovery_member *) my_hash_search(hash_arg, (uchar *)& xid_arg, sizeof(xid_arg)))) member->in_engine_prepare++; else - member= xid_member_insert(hash_arg, xid_arg, ptr_mem_root); + member= xid_member_insert(hash_arg, xid_arg, ptr_mem_root, full_xid_arg); return member == NULL; } @@ -2479,7 +2487,10 @@ static void xarecover_do_commit_or_rollback(handlerton *hton, xid_recovery_member *member= arg->member; Binlog_offset *ptr_commit_max= arg->binlog_coord; - x.set(member->xid); + if (!member->full_xid) + x.set(member->xid); + else + x= *member->full_xid; rc= xarecover_decide_to_commit(member, ptr_commit_max) ? hton->commit_by_xid(hton, &x) : hton->rollback_by_xid(hton, &x); @@ -2601,10 +2612,13 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, for (int i=0; i < got; i ++) { - my_xid x= IF_WSREP(wsrep_is_wsrep_xid(&info->list[i]) ? - wsrep_xid_seqno(&info->list[i]) : - info->list[i].get_my_xid(), - info->list[i].get_my_xid()); + my_xid x= info->list[i].get_my_xid(); + bool is_server_xid= x > 0; + +#ifdef WITH_WSREP + if (!is_server_xid && wsrep_is_wsrep_xid(&info->list[i])) + x= wsrep_xid_seqno(&info->list[i]); +#endif if (!x) // not "mine" - that is generated by external TM { DBUG_EXECUTE("info",{ @@ -2630,7 +2644,9 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, */ if (info->mem_root) { - if (xid_member_replace(info->commit_list, x, info->mem_root)) + // remember "full" xid too when it's not in mysql format + if (xid_member_replace(info->commit_list, x, info->mem_root, + is_server_xid? NULL : &info->list[i])) { info->error= true; sql_print_error("Error in memory allocation at xarecover_handlerton"); @@ -2651,8 +2667,7 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, }); } } - else if (WSREP_ON || - tc_heuristic_recover == TC_HEURISTIC_RECOVER_ROLLBACK) + else if (!info->mem_root) { int rc= hton->rollback_by_xid(hton, info->list+i); if (rc == 0) diff --git a/sql/handler.h b/sql/handler.h index 2f15ec8f389..7ad00ee546b 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -956,10 +956,12 @@ struct xid_recovery_member uint in_engine_prepare; // number of engines that have xid prepared bool decided_to_commit; Binlog_offset binlog_coord; // semisync recovery binlog offset + XID *full_xid; // needed by wsrep or past it recovery - xid_recovery_member(my_xid xid_arg, uint prepare_arg, bool decided_arg) + xid_recovery_member(my_xid xid_arg, uint prepare_arg, bool decided_arg, + XID *full_xid_arg) : xid(xid_arg), in_engine_prepare(prepare_arg), - decided_to_commit(decided_arg) {}; + decided_to_commit(decided_arg), full_xid(full_xid_arg) {}; }; /* for recover() handlerton call */