-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Add initial support for capabilities #4987
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
f336afe
Add initial support for capabilities
morgo 030c2fd
Removed MYSQL_FLAVOR variable precedence
morgo 118f3e7
Address PR feedback (WIP)
morgo a8343f9
Merge remote-tracking branch 'upstream/master' into morgo-mysql-capab…
morgo 469a94e
Fixed mysql_safe to not use capabilitities
morgo cd47164
fix version detection
morgo e1ff1b7
Fix style, re-add EXTRA_MY_CNF from review
morgo ed86bd5
Address review feedback
morgo 79dbc8e
address remaining feedback
morgo a02bbad
Remove rogue added space
morgo 5339cbb
Address PR feedback
morgo f881735
Address PR feedback
morgo 2fde7d4
Fix broken test
morgo 555f559
Fixed tests
morgo e7f7474
Addressed PR feedback
morgo 1ecd822
update copyright
morgo d4ca143
Remove unset MYSQL_FLAVOR
morgo e4b487b
Make sure error is caught.
morgo bc08f6a
Address PR Feedback
morgo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| # reserved for future use |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # Options for enabling GTID | ||
| # https://dev.mysql.com/doc/refman/5.6/en/replication-gtids-howto.html | ||
| gtid_mode = ON | ||
| log_bin | ||
| log_slave_updates | ||
| enforce_gtid_consistency | ||
|
|
||
| # Crash-safe replication settings. | ||
| master_info_repository = TABLE | ||
| relay_log_info_repository = TABLE | ||
| relay_log_purge = 1 | ||
| relay_log_recovery = 1 | ||
|
|
||
|
morgo marked this conversation as resolved.
|
||
| # Semi-sync replication is required for automated unplanned failover | ||
| # (when the master goes away). Here we just load the plugin so it's | ||
| # available if desired, but it's disabled at startup. | ||
| # | ||
| # If the -enable_semi_sync flag is used, VTTablet will enable semi-sync | ||
| # at the proper time when replication is set up, or when masters are | ||
| # promoted or demoted. | ||
| plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so | ||
|
|
||
| # When semi-sync is enabled, don't allow fallback to async | ||
| # if you get no ack, or have no slaves. This is necessary to | ||
| # prevent alternate futures when doing a failover in response to | ||
| # a master that becomes unresponsive. | ||
| rpl_semi_sync_master_timeout = 1000000000000000000 | ||
| rpl_semi_sync_master_wait_no_slave = 1 | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,248 @@ | ||
| /* | ||
| Copyright 2019 The Vitess Authors | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| */ | ||
|
|
||
| /* | ||
| Detect server flavors and capabilities | ||
| */ | ||
|
|
||
| package mysqlctl | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "regexp" | ||
| "strconv" | ||
| "strings" | ||
|
|
||
| vtenv "vitess.io/vitess/go/vt/env" | ||
| "vitess.io/vitess/go/vt/log" | ||
| ) | ||
|
|
||
| type serverVersion []int | ||
|
|
||
| const ( | ||
| flavorMySQL = "mysql" | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| flavorPercona = "percona" | ||
| flavorMariaDB = "mariadb" | ||
| ) | ||
|
|
||
| const ( | ||
| CapabilityMySQLUpgradeInServer = 1 << iota | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| CapabilityInitializeInServer | ||
| CapabilityMySQLxEnabledByDefault | ||
| CapabilityPersistConfig | ||
| CapabilityShutdownCommand | ||
| CapabilityBackupLocks | ||
| CapabilityDefaultUtf8mb4 | ||
| CapabilitySemiSyncEnabledByDefault | ||
| CapabilitySystemd // often package specific, not just version specific | ||
| ) | ||
|
|
||
| var ( | ||
| minimumMySQLUpgradeInServer = serverVersion{8, 0, 16} | ||
| minimumMySQLInitializeInServer = serverVersion{5, 7, 0} | ||
| minimumMySQLxEnabledByDefault = serverVersion{8, 0, 11} | ||
| minimumMySQLPersistConfig = serverVersion{8, 0, 0} | ||
| minimumMySQLShutdownCommand = serverVersion{5, 7, 9} | ||
| minimumMySQLBackupLocks = serverVersion{8, 0, 0} | ||
| minimumMySQLDefaultUtf8mb4 = serverVersion{8, 0, 0} | ||
| minimumMariaDBSemiSyncEnabledByDefault = serverVersion{10, 3, 3} | ||
| minimumMariaDBShutdownCommand = serverVersion{10, 0, 4} | ||
| ) | ||
|
|
||
| // HasCapability will return a bool value of if the server | ||
| // has a particular feature, based on a known list of | ||
| // introduced versions and detection. This gets more | ||
| // complicated in MySQL 8.0 as several features were introduced | ||
| // after the initial GA release. | ||
| func (mysqld *Mysqld) HasCapability(capability int) bool { | ||
|
|
||
| switch capability { | ||
| case CapabilityMySQLUpgradeInServer: | ||
| return mysqld.IsMySQLLike() && mysqld.greaterThan(minimumMySQLUpgradeInServer) | ||
| case CapabilityInitializeInServer: | ||
| return mysqld.IsMySQLLike() && mysqld.greaterThan(minimumMySQLInitializeInServer) | ||
| case CapabilityMySQLxEnabledByDefault: | ||
| return mysqld.IsMySQLLike() && mysqld.greaterThan(minimumMySQLxEnabledByDefault) | ||
| case CapabilityPersistConfig: | ||
| return mysqld.IsMySQLLike() && mysqld.greaterThan(minimumMySQLPersistConfig) | ||
| case CapabilityShutdownCommand: | ||
| return mysqld.IsMySQLLike() && mysqld.greaterThan(minimumMySQLShutdownCommand) || mysqld.IsMariaDB() && mysqld.greaterThan(minimumMariaDBShutdownCommand) | ||
| case CapabilityBackupLocks: | ||
| return mysqld.IsMySQLLike() && mysqld.greaterThan(minimumMySQLBackupLocks) | ||
| case CapabilityDefaultUtf8mb4: | ||
| return mysqld.IsMySQLLike() && mysqld.greaterThan(minimumMySQLDefaultUtf8mb4) | ||
| case CapabilitySemiSyncEnabledByDefault: | ||
| return mysqld.IsMariaDB() && mysqld.greaterThan(minimumMariaDBSemiSyncEnabledByDefault) | ||
| case CapabilitySystemd: | ||
| dir, err := vtenv.VtMysqlRoot() | ||
| if err != nil { | ||
| return false | ||
| } | ||
| _, err = binaryPath(dir, "mysqld_safe") | ||
| return err != nil // if there is no mysqld_safe, it means this platform is systemd | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| default: | ||
| log.Warningf("%d: unknown capability", capability) | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| return false | ||
| } | ||
|
|
||
| } | ||
|
|
||
| func (mysqld *Mysqld) greaterThan(version serverVersion) bool { | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| if mysqld.version[0] > version[0] { | ||
| return true | ||
| } else if mysqld.version[0] == version[0] && mysqld.version[1] > version[1] { | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| return true | ||
| } else if mysqld.version[0] == version[0] && mysqld.version[1] == version[1] && mysqld.version[2] >= version[2] { | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| return true | ||
| } else { | ||
| return false | ||
| } | ||
| } | ||
|
|
||
| // IsMySQLLike tests if the server is either MySQL | ||
| // or Percona Server. At least currently, Vitess doesn't | ||
| // make use of any specific Percona Server features. | ||
| func (mysqld *Mysqld) IsMySQLLike() bool { | ||
| return mysqld.flavor == flavorMySQL || mysqld.flavor == flavorPercona | ||
| } | ||
|
|
||
| // IsMariaDB tests if the server is MariaDB. | ||
| // IsMySQLLike() and IsMariaDB() are mutually exclusive | ||
| func (mysqld *Mysqld) IsMariaDB() bool { | ||
| return mysqld.flavor == flavorMariaDB | ||
| } | ||
|
|
||
| // MajorVersion returns an integer for the leading version. | ||
| // For example 8 in the case of MySQL 8.0.11, or | ||
| // 5 in the case of 5.6.15 | ||
| func (mysqld *Mysqld) MajorVersion() int { | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| return mysqld.version[0] | ||
| } | ||
|
|
||
| // MinorVersion returns an integer for the second version | ||
| // For example 6 in the case of 5.6.11 | ||
| func (mysqld *Mysqld) MinorVersion() int { | ||
| return mysqld.version[1] | ||
| } | ||
|
|
||
| // PatchVersion returns an integer for the third | ||
| // part of the version. For example 11 in the case of | ||
| // 5.6.11 | ||
| func (mysqld *Mysqld) PatchVersion() int { | ||
| return mysqld.version[2] | ||
| } | ||
|
|
||
| func (mysqld *Mysqld) getVersionString() (string, error) { | ||
|
|
||
|
morgo marked this conversation as resolved.
Outdated
|
||
| mysqlRoot, err := vtenv.VtMysqlRoot() | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
| mysqldPath, err := binaryPath(mysqlRoot, "mysqld") | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
|
|
||
| _, version, err := execCmd(mysqldPath, []string{"--version"}, nil, mysqlRoot, nil) | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
|
|
||
| return version, nil | ||
|
|
||
| } | ||
|
|
||
| func (mysqld *Mysqld) detectFlavor() (string, error) { | ||
|
|
||
| mysqlFlavor := os.Getenv("MYSQL_FLAVOR") | ||
| if len(mysqlFlavor) > 0 { | ||
| mysqlFlavor = strings.ToLower(mysqlFlavor)[0:5] | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
|
|
||
| if mysqlFlavor == "mysql" { | ||
| return flavorMySQL, nil | ||
| } else if mysqlFlavor == "maria" { | ||
| return flavorMariaDB, nil | ||
| } | ||
| } | ||
|
|
||
| // Flavor was either not defined in ENV, or unknown | ||
|
|
||
| version, err := mysqld.getVersionString() | ||
| if err != nil { | ||
| return version, err | ||
| } | ||
|
|
||
| // Check if the flavor has been defined | ||
| // This takes first precedence. | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
|
|
||
| if strings.Contains(version, "MySQL Community Server") { | ||
| return flavorMySQL, nil | ||
| } else if strings.Contains(version, "Percona") { | ||
| return flavorPercona, nil | ||
| } else if strings.Contains(version, "MariaDB") { | ||
| return flavorMariaDB, nil | ||
| } | ||
|
|
||
| return "", fmt.Errorf("Could not autodetect flavor!") | ||
|
|
||
| } | ||
|
|
||
| func (mysqld *Mysqld) detectVersion() (serverVersion, error) { | ||
|
|
||
| mysqlFlavor := strings.ToLower(os.Getenv("MYSQL_FLAVOR")) | ||
|
|
||
| // Try not to be too smart with version parsing. | ||
| // Assume GA versions | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| switch mysqlFlavor { | ||
| case "mysql56": | ||
| return serverVersion{5, 6, 10}, nil | ||
| case "mysql57": | ||
| return serverVersion{5, 7, 9}, nil | ||
| case "mysql80": | ||
| return serverVersion{8, 0, 11}, nil | ||
| case "mariadb10": | ||
| return serverVersion{10, 0, 10}, nil | ||
| case "mariadb101": | ||
| return serverVersion{10, 1, 8}, nil | ||
| case "mariadb102": | ||
| return serverVersion{10, 2, 6}, nil | ||
| case "mariadb103": | ||
| return serverVersion{10, 3, 7}, nil | ||
| case "mariadb104": | ||
| return serverVersion{10, 4, 6}, nil | ||
| } | ||
|
|
||
| // Could not understand version from ENV | ||
| // Time to auto-detect instead | ||
|
|
||
| version, err := mysqld.getVersionString() | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| // Detect server version | ||
| re := regexp.MustCompile(`Ver [0-9]+\.[0-9]+\.[0-9]+`) | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| ver := re.Find([]byte(version))[4:] | ||
| re = regexp.MustCompile(`[0-9]+`) | ||
|
morgo marked this conversation as resolved.
Outdated
|
||
| v := re.FindAll([]byte(ver), -1) | ||
| major, _ := strconv.Atoi(string(v[0])) | ||
| minor, _ := strconv.Atoi(string(v[1])) | ||
| patch, _ := strconv.Atoi(string(v[2])) | ||
|
|
||
| return serverVersion{major, minor, patch}, nil | ||
|
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.