Skip to content

Commit 082ab30

Browse files
author
Hemant Dangi
committed
Bug#25876807: FOR DIFFERENT VERSION (5.7 AND 8.0) GROUP, LEADER SHOULD BE
ONLY FROM LOWER VERSION PROBLEM STATEMENT ================= When a group contain members of two different versions (5.7 & 8.0), higher version members are put in read compatability mode and cannot write to the group. In single primary-mode, currently the primary member can be elected from the higher version members also thus making a member what should be in read mode writable, what can lead to failures in the lower version members. PROPOSED SOLUTIONS ================== The primary member should be elected from lower version members i.e 5.7, in single primary-mode. And so only the members with the lowest versions should participate in the election.
1 parent 5562d0d commit 082ab30

File tree

4 files changed

+137
-15
lines changed

4 files changed

+137
-15
lines changed

rapid/plugin/group_replication/include/gcs_event_handlers.h

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -40,7 +40,7 @@ struct Group_member_info_pointer_comparator
4040
bool operator()(Group_member_info* one,
4141
Group_member_info* other) const
4242
{
43-
return *one < *other;
43+
return other->has_greater_uuid(one);
4444
}
4545
};
4646

@@ -132,6 +132,32 @@ class Plugin_gcs_events_handler: public Gcs_communication_event_listener,
132132
*/
133133
void handle_leader_election_if_needed() const;
134134

135+
/**
136+
Sort lower version members based on uuid
137+
138+
@param all_members_info the vector with members info
139+
140+
@return first iterator position where members version increase.
141+
*/
142+
void sort_members_for_election(
143+
std::vector<Group_member_info*>* all_members_info,
144+
std::vector<Group_member_info*>::iterator lowest_version_end) const;
145+
146+
/**
147+
Sort members based on member_version and get first iterator position
148+
where member version differs.
149+
150+
@param all_members_info the vector with members info
151+
@param lowest_version_end first iterator position where members version
152+
increases.
153+
154+
@note from the start of the list to the returned iterator, all members have
155+
the lowest version in the group.
156+
*/
157+
std::vector<Group_member_info*>::iterator
158+
sort_and_get_lowest_version_member_position(
159+
std::vector<Group_member_info*>* all_members_info) const;
160+
135161
int
136162
process_local_exchanged_data(const Exchanged_data &exchanged_data) const;
137163

rapid/plugin/group_replication/include/member_info.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,29 @@ class Group_member_info: public Plugin_gcs_message
291291
static std::string get_configuration_flags_string(const uint32 configuation_flags);
292292

293293
/**
294-
@return Compare two members using "operator <"
294+
@return Compare two members using member version
295295
*/
296-
static bool comparator_group_member_info(Group_member_info *m1, Group_member_info *m2);
296+
static bool comparator_group_member_version(Group_member_info *m1, Group_member_info *m2);
297+
298+
/**
299+
@return Compare two members using server uuid
300+
*/
301+
static bool comparator_group_member_uuid(Group_member_info *m1, Group_member_info *m2);
302+
303+
/**
304+
Return true if member version is higher than other member version
305+
*/
306+
bool has_greater_version(Group_member_info *other);
307+
308+
/**
309+
Return true if server uuid is higher than other member server uuid
310+
*/
311+
bool has_greater_uuid(Group_member_info *other);
312+
313+
/**
314+
Return true if server uuid is equal than other member server uuid
315+
*/
316+
bool has_equal_uuid(Group_member_info *other);
297317

298318
/**
299319
Redefinition of operate == and <. They operate upon the uuid

rapid/plugin/group_replication/src/gcs_event_handlers.cc

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,55 @@ Plugin_gcs_events_handler::was_member_expelled_from_group(const Gcs_view& view)
400400
DBUG_RETURN(result);
401401
}
402402

403+
std::vector<Group_member_info*>::iterator
404+
Plugin_gcs_events_handler::sort_and_get_lowest_version_member_position(
405+
std::vector<Group_member_info*>* all_members_info) const
406+
{
407+
std::vector<Group_member_info*>::iterator it;
408+
409+
// sort in ascending order of lower member version
410+
std::sort(all_members_info->begin(), all_members_info->end(),
411+
Group_member_info::comparator_group_member_version);
412+
413+
/* if vector contains only single version then leader should be picked from
414+
all members
415+
*/
416+
std::vector<Group_member_info*>::iterator lowest_version_end=
417+
all_members_info->end();
418+
419+
/* first member will have lowest version as members are already
420+
sorted above using member_version.
421+
*/
422+
it= all_members_info->begin();
423+
Group_member_info* first_member= *it;
424+
uint32 lowest_major_version=
425+
first_member->get_member_version().get_major_version();
426+
427+
/* to avoid read compatibility issue leader should be picked only from lowest
428+
version members so save position where member version differs
429+
*/
430+
for(it= all_members_info->begin() + 1; it != all_members_info->end(); it++)
431+
{
432+
if (lowest_major_version != (*it)->get_member_version().get_major_version())
433+
{
434+
lowest_version_end= it;
435+
break;
436+
}
437+
}
438+
439+
return lowest_version_end;
440+
}
441+
442+
void Plugin_gcs_events_handler::sort_members_for_election(
443+
std::vector<Group_member_info*>* all_members_info,
444+
std::vector<Group_member_info*>::iterator lowest_version_end) const
445+
{
446+
// sort only lower version members as they only will be needed to pick leader
447+
std::sort(all_members_info->begin(), lowest_version_end,
448+
Group_member_info::comparator_group_member_uuid);
449+
450+
}
451+
403452
void Plugin_gcs_events_handler::handle_leader_election_if_needed() const
404453
{
405454
// take action if in single leader mode
@@ -415,8 +464,16 @@ void Plugin_gcs_events_handler::handle_leader_election_if_needed() const
415464
group_member_mgr->get_all_members();
416465

417466
std::vector<Group_member_info*>::iterator it;
418-
std::sort(all_members_info->begin(), all_members_info->end(),
419-
Group_member_info::comparator_group_member_info);
467+
std::vector<Group_member_info*>::iterator lowest_version_end;
468+
469+
/* sort members based on member_version and get first iterator position
470+
where member version differs
471+
*/
472+
lowest_version_end=
473+
sort_and_get_lowest_version_member_position(all_members_info);
474+
475+
// sort lower version members based on uuid
476+
sort_members_for_election(all_members_info, lowest_version_end);
420477

421478
/*
422479
1. Iterate over the list of all members and check if there is a primary
@@ -476,11 +533,14 @@ void Plugin_gcs_events_handler::handle_leader_election_if_needed() const
476533
477534
The assumption is that std::sort(...) is deterministic
478535
on all members.
536+
537+
To pick leaders from only lowest version members loop
538+
till lowest_version_end.
479539
*/
480540
if (the_primary == NULL)
481541
{
482542
for (it= all_members_info->begin();
483-
it != all_members_info->end() && the_primary == NULL;
543+
it != lowest_version_end && the_primary == NULL;
484544
it++)
485545
{
486546
Group_member_info* mi= *it;

rapid/plugin/group_replication/src/member_info.cc

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -392,12 +392,6 @@ bool Group_member_info::is_conflict_detection_enabled()
392392
return conflict_detection_enable;
393393
}
394394

395-
bool
396-
Group_member_info::operator <(Group_member_info& other)
397-
{
398-
return this->get_uuid().compare(other.get_uuid()) < 0;
399-
}
400-
401395
bool
402396
Group_member_info::operator ==(Group_member_info& other)
403397
{
@@ -466,12 +460,34 @@ Group_member_info::get_configuration_flags_string(const uint32 configuation_flag
466460
}
467461

468462
bool
469-
Group_member_info::comparator_group_member_info(Group_member_info *m1,
463+
Group_member_info::comparator_group_member_version(Group_member_info *m1,
464+
Group_member_info *m2)
465+
{
466+
return m2->has_greater_version(m1);
467+
}
468+
469+
bool
470+
Group_member_info::comparator_group_member_uuid(Group_member_info *m1,
470471
Group_member_info *m2)
471472
{
472-
return *m1 < *m2;
473+
return m2->has_greater_uuid(m1);
473474
}
474475

476+
bool
477+
Group_member_info::has_greater_version(Group_member_info *other)
478+
{
479+
if (this->member_version->get_major_version() >
480+
other->member_version->get_major_version())
481+
return true;
482+
483+
return false;
484+
}
485+
486+
bool
487+
Group_member_info::has_greater_uuid(Group_member_info *other)
488+
{
489+
return this->get_uuid().compare(other->get_uuid()) < 0;
490+
}
475491

476492
Group_member_info_manager::
477493
Group_member_info_manager(Group_member_info* local_member_info)

0 commit comments

Comments
 (0)