Skip to content

Commit 152201a

Browse files
committed
Bug#35605595 MySQL shell needs to support GTID tags
Starting in 8.3.0, the server supports GTID with tags. Essentially, after the UUID component of the GTID and before the range, there might now be a tag to associate with the GTID. This means that a GTID is now uniquely identified with UUID+tag (empty tags are valid and represent the previous, non-tagged GTIDs). The AdminAPI needs to call several server APIS (i.e: gtid_subtract()) in order to process and compare GTIDs from different servers, like for example when joining an instances to a Cluster. But since the primary and the new instance can have different version, this means that the new instance (running 8.3.0) can have tagged GTIDs, which the primary (running a version less than 8.3.0) doesn't know how to process. In this case, the primary throws an error (malformed GTID), which will abort, for example, a cluster.addInstance() request. This patch takes this scenario into account by checking the server version and if the GTIDs of a joining member are tagged. If the server doesn't support tagged GTIDs and they are present, then the current command is aborted and the user informed that, in order to use tagged GTIDs, all members of a Cluster or ReplicaSet must be at version 8.3.0 or newer. Change-Id: I47e0db9c355cd815ad6b389e6e280e30d07353c1
1 parent b88dad5 commit 152201a

File tree

23 files changed

+1164
-414
lines changed

23 files changed

+1164
-414
lines changed

modules/adminapi/cluster_set/cluster_set_impl.cc

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3021,50 +3021,54 @@ void Cluster_set_impl::ensure_transaction_set_consistent_and_recoverable(
30213021
bool *out_is_recoverable) {
30223022
mysqlshdk::mysql::Gtid_set missing_view_gtids;
30233023
mysqlshdk::mysql::Gtid_set errant_gtids;
3024-
mysqlshdk::mysql::Gtid_set missing_gtids;
30253024
mysqlshdk::mysql::Gtid_set unrecoverable_gtids;
30263025

3027-
std::vector<std::string> allowed_errant_uuids;
3028-
std::vector<Cluster_set_member_metadata> members;
3026+
{
3027+
// purged GTIDs from all members of the primary
3028+
std::vector<mysqlshdk::mysql::Gtid_set> purged_gtids;
30293029

3030-
// purged GTIDs from all members of the primary
3031-
std::vector<mysqlshdk::mysql::Gtid_set> purged_gtids;
3030+
primary_cluster->execute_in_members(
3031+
[&purged_gtids](const std::shared_ptr<Instance> &instance,
3032+
const Cluster_impl::Instance_md_and_gr_member &) {
3033+
auto purged = mysqlshdk::mysql::Gtid_set::from_gtid_purged(*instance);
30323034

3033-
primary_cluster->execute_in_members(
3034-
[&purged_gtids](const std::shared_ptr<Instance> &instance,
3035-
const Cluster_impl::Instance_md_and_gr_member &) {
3036-
auto purged = mysqlshdk::mysql::Gtid_set::from_gtid_purged(*instance);
3035+
log_debug("gtid_purged@%s=%s", instance->descr().c_str(),
3036+
purged.str().c_str());
3037+
purged_gtids.emplace_back(purged);
3038+
return true;
3039+
},
3040+
[](const shcore::Error &err,
3041+
const Cluster_impl::Instance_md_and_gr_member &i) {
3042+
log_debug("could not connect to %s:%i to query gtid_purged: %s",
3043+
i.second.host.c_str(), i.second.port, err.format().c_str());
3044+
return true;
3045+
});
30373046

3038-
log_debug("gtid_purged@%s=%s", instance->descr().c_str(),
3039-
purged.str().c_str());
3040-
purged_gtids.emplace_back(purged);
3041-
return true;
3042-
},
3043-
[](const shcore::Error &err,
3044-
const Cluster_impl::Instance_md_and_gr_member &i) {
3045-
log_debug("could not connect to %s:%i to query gtid_purged: %s",
3046-
i.second.host.c_str(), i.second.port, err.format().c_str());
3047-
return true;
3048-
});
3047+
std::vector<Cluster_set_member_metadata> members;
3048+
get_metadata_storage()->get_cluster_set(get_id(), true, nullptr, &members);
30493049

3050-
get_metadata_storage()->get_cluster_set(get_id(), true, nullptr, &members);
3051-
for (const auto &m : members) {
3052-
allowed_errant_uuids.push_back(m.cluster.view_change_uuid);
3053-
}
3050+
std::vector<std::string> allowed_errant_uuids;
3051+
allowed_errant_uuids.reserve(members.size());
3052+
for (const auto &m : members) {
3053+
allowed_errant_uuids.push_back(m.cluster.view_change_uuid);
3054+
}
30543055

3055-
mysqlshdk::mysql::compute_joining_replica_gtid_state(
3056-
*primary, mysqlshdk::mysql::Gtid_set::from_gtid_executed(*primary),
3057-
purged_gtids, mysqlshdk::mysql::Gtid_set::from_gtid_executed(*replica),
3058-
allowed_errant_uuids, &missing_gtids, &unrecoverable_gtids, &errant_gtids,
3059-
&missing_view_gtids);
3056+
mysqlshdk::mysql::Gtid_set missing_gtids;
30603057

3061-
log_info(
3062-
"GTID check between %s and %s (%s) missing=%s errant=%s unrecoverable=%s "
3063-
"vcle=%s\n",
3064-
replica->descr().c_str(), primary_cluster->get_name().c_str(),
3065-
primary->descr().c_str(), missing_gtids.str().c_str(),
3066-
errant_gtids.str().c_str(), unrecoverable_gtids.str().c_str(),
3067-
missing_view_gtids.str().c_str());
3058+
mysqlshdk::mysql::compute_joining_replica_gtid_state(
3059+
*primary, mysqlshdk::mysql::Gtid_set::from_gtid_executed(*primary),
3060+
purged_gtids, mysqlshdk::mysql::Gtid_set::from_gtid_executed(*replica),
3061+
allowed_errant_uuids, &missing_gtids, &unrecoverable_gtids,
3062+
&errant_gtids, &missing_view_gtids);
3063+
3064+
log_info(
3065+
"GTID check between '%s' and '%s' ('%s'): missing='%s' errant='%s' "
3066+
"unrecoverable='%s' vcle='%s'",
3067+
replica->descr().c_str(), primary_cluster->get_name().c_str(),
3068+
primary->descr().c_str(), missing_gtids.str().c_str(),
3069+
errant_gtids.str().c_str(), unrecoverable_gtids.str().c_str(),
3070+
missing_view_gtids.str().c_str());
3071+
}
30683072

30693073
if (out_is_recoverable) *out_is_recoverable = true;
30703074

modules/adminapi/common/common.cc

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,8 +1724,6 @@ std::vector<Instance_gtid_info> filter_primary_candidates(
17241724
const std::vector<Instance_gtid_info> &gtid_info,
17251725
const std::function<bool(const Instance_gtid_info &,
17261726
const Instance_gtid_info &)> &on_conflit) {
1727-
using mysqlshdk::mysql::Gtid_set_relation;
1728-
17291727
if (gtid_info.empty()) return {};
17301728

17311729
std::vector<Instance_gtid_info> candidates;
@@ -1740,14 +1738,17 @@ std::vector<Instance_gtid_info> filter_primary_candidates(
17401738
server, freshest_instance->gtid_executed, inst.gtid_executed);
17411739

17421740
switch (rel) {
1741+
using mysqlshdk::mysql::Gtid_set_relation;
1742+
17431743
// Conflicting GTID sets
17441744
case Gtid_set_relation::DISJOINT:
17451745
case Gtid_set_relation::INTERSECTS:
17461746
if (!on_conflit)
1747-
throw shcore::Exception("Conflicting transaction sets between " +
1748-
freshest_instance->server + " and " +
1749-
inst.server,
1750-
SHERR_DBA_DATA_ERRANT_TRANSACTIONS);
1747+
throw shcore::Exception(
1748+
shcore::str_format(
1749+
"Conflicting transaction sets between '%s' and '%s'",
1750+
freshest_instance->server.c_str(), inst.server.c_str()),
1751+
SHERR_DBA_DATA_ERRANT_TRANSACTIONS);
17511752

17521753
if (!on_conflit(*freshest_instance, inst)) return candidates;
17531754
break;
@@ -1919,7 +1920,7 @@ bool wait_for_gtid_set_safe(const mysqlshdk::mysql::IInstance &target_instance,
19191920
mysqlshdk::mysql::Gtid_set::from_gtid_executed(target_instance);
19201921

19211922
return mysqlshdk::mysql::estimate_gtid_set_size(
1922-
gtid_set_primary.subtract(gtid_set_target, target_instance));
1923+
gtid_set_primary.subtract(gtid_set_target, target_instance).str());
19231924
};
19241925

19251926
using Progress_reporting = Shell_options::Storage::Progress_reporting;

0 commit comments

Comments
 (0)