[improve](env) Ensure next majority is met before drop an alive follower (#28101)

Here is an example:

```
mysql> ALTER SYSTEM DROP FOLLOWER "127.0.0.1:19017";
ERROR 1105 (HY000): errCode = 2, detailMessage = Unable to drop this alive
follower, because the quorum requirements are not met after this command
execution. Current num alive followers 2, num followers 3, majority after
execution 2
```
This commit is contained in:
walter
2023-12-09 01:41:38 +08:00
committed by GitHub
parent 99be9d6ad3
commit 99b38ddca7

View File

@ -2768,6 +2768,10 @@ public class Env {
throw new DdlException(role.toString() + " does not exist[" + NetUtils
.getHostPortInAccessibleFormat(host, port) + "]");
}
if (role == FrontendNodeType.FOLLOWER && fe.isAlive()) {
// Try drop an alive follower, check the quorum safety.
ensureSafeToDropAliveFollower();
}
int targetFollowerCount = getFollowerCount() - 1;
if (fe.getRole() == FrontendNodeType.FOLLOWER || fe.getRole() == FrontendNodeType.REPLICA) {
@ -2796,6 +2800,30 @@ public class Env {
helperNodes.removeIf(node -> node.getHost().equals(host) && node.getPort() == port);
}
private void ensureSafeToDropAliveFollower() throws DdlException {
int numFollower = 0;
int numAliveFollower = 0;
for (Frontend fe : frontends.values()) {
if (fe.getRole() == FrontendNodeType.FOLLOWER) {
numFollower += 1;
if (fe.isAlive()) {
numAliveFollower += 1;
}
}
}
int nextMajority = ((numFollower - 1) / 2) + 1;
if (nextMajority + 1 <= numAliveFollower) {
return;
}
LOG.warn("Drop an alive follower is not safety. Current alive followers {}, followers {}, next majority: {}",
numAliveFollower, numFollower, nextMajority);
throw new DdlException("Unable to drop this alive follower, because the quorum requirements "
+ "are not met after this command execution. Current num alive followers "
+ numAliveFollower + ", num followers " + numFollower + ", majority after execution " + nextMajority);
}
public Frontend checkFeExist(String host, int port) {
for (Frontend fe : frontends.values()) {
if (fe.getEditLogPort() != port) {