-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
restore: Run PITR through mysqlctl #13123
restore: Run PITR through mysqlctl #13123
Conversation
Review ChecklistHello reviewers! 👋 Please follow this checklist when reviewing this Pull Request. General
If a new flag is being introduced:
If a workflow is added or modified:
Bug fixes
Non-trivial changes
New/Existing features
Backward compatibility
|
a51a422
to
2f03810
Compare
When we run a retore remotely on the vttablet, we need to run the partial restore logic through mysqlctl to ensure we run it with the correct MySQL binaries. It adds additional safety checks for using `Mysqld` because it's reused between both the local MySQL interaction and `mysqlctl` but also as a remote interface used from `vttablet`. This safety check means that we should never run certain things when running remotely inside `vttablet`, which is identified by the `socketFile` being set or not. When it is set, we now panic on certain actions we know are not going to work. By adding this panic we can ensure we catch uses like the restore usage earlier since it would break if we do anything unsupported. Signed-off-by: Dirkjan Bussink <[email protected]>
2f03810
to
8061c55
Compare
func (c *capabilitySet) hasDisableRedoLog() bool { | ||
return c.isMySQLLike() && c.version.atLeast(ServerVersion{Major: 8, Minor: 0, Patch: 21}) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have removed this function since nothing is using atm. I'd like to reduce anything that checks capabilities to as little as possible, since this PR also further restricts that these capabilities can only be used properly inside mysqlctl
and with less surface, we have less potential issues where it can be used wrong.
if socketFile != "" { | ||
log.Info("mysqld is remote. Skipping flavor detection") | ||
return result | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ensures we don't set up capabilities when we can't correctly detect them.
@@ -286,7 +293,7 @@ func (mysqld *Mysqld) RunMysqlUpgrade() error { | |||
return fmt.Errorf("can't dial mysqlctld: %v", err) | |||
} | |||
defer client.Close() | |||
return client.RunMysqlUpgrade(context.TODO()) | |||
return client.RunMysqlUpgrade(ctx) | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems simplest to pass in the context we already have in all the callers further up in the call chain.
@@ -635,6 +642,7 @@ func execCmd(name string, args, env []string, dir string, input io.Reader) (cmd | |||
// binaryPath does a limited path lookup for a command, | |||
// searching only within sbin and bin in the given root. | |||
func binaryPath(root, binary string) (string, error) { | |||
noSocketFile() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anywhere we're going to check if a certain binary is available, implies we need to be running inside mysqlctl
. This ensures we error out hard when we try to end up calling this somewhere else.
Everything is correct here today, this is a safety mechanism so that we don't accidentally add broken usage in the future.
} | ||
res := qr.Named().Row() | ||
version, _ := res.ToString("@@global.version") | ||
return version | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to GetVersionComment
, we get the version number here at runtime from the actual running MySQL instance. This ensures we get the right version and not the local binary.
} | ||
defer client.Close() | ||
return client.ApplyBinlogFile(ctx, binlogFile, mysql.EncodePosition(restorePos)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now part of the interface and also has a remote version so we can run this correctly for restores through mysqlctl
.
// $ mysqlbinlog --include-gtids binlog.file | mysql | ||
func (mysqld *Mysqld) applyBinlogFile(binlogFile string, includeGTIDs mysql.GTIDSet) error { | ||
func (mysqld *Mysqld) ApplyBinlogFile(ctx context.Context, binlogFile string, restorePos mysql.Position) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing this to mysql.Position
makes it easier to serialize / deserialize and better matches how we use a GTID position in other places here.
BinlogRestorePosition: binlogRestorePosition, | ||
} | ||
return c.withRetry(ctx, func() error { | ||
_, err := c.c.ApplyBinlogFile(ctx, req) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a fan of c.c.
but unrelated to this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copied this basically from the other things we have to be consistent.
log.Errorf("Unexpected number of rows: %v", qr.Rows) | ||
return "" | ||
} | ||
res := qr.Named().Row() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW the function Row()
returns nil
if the number of rows != 1
. So if you wanted, you could rewrite the integrity check above from if len(qr.Rows) != 1 {
to (down in this line) if res == nil
. Whichever you feel more comfortable with, seeing that the former is more explicit and the latter is implied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, this is basically a copy paste of how the comment version works and mostly the same to stay consistent with that.
After the changes in vitessio#13123, I realized that there's no cases left where we actually use or depend on `MYSQL_FLAVOR`. This means we can actually remove usages of `MYSQL_FLAVOR`. It doesn't yet remove it from the artifacts we build, because we shouldn't clean that up until v18 then because users might mix versions during the upgrade and we don't want to have old code that still depends on this fail then. Signed-off-by: Dirkjan Bussink <[email protected]>
* mysqlctl: Remove usage of MYSQL_FLAVOR After the changes in #13123, I realized that there's no cases left where we actually use or depend on `MYSQL_FLAVOR`. This means we can actually remove usages of `MYSQL_FLAVOR`. It doesn't yet remove it from the artifacts we build, because we shouldn't clean that up until v18 then because users might mix versions during the upgrade and we don't want to have old code that still depends on this fail then. Signed-off-by: Dirkjan Bussink <[email protected]> * Add release note item for removed `MYSQL_FLAVOR`. Signed-off-by: Dirkjan Bussink <[email protected]> --------- Signed-off-by: Dirkjan Bussink <[email protected]>
When we run a restore remotely on the vttablet, we need to run the PITR logic through mysqlctl to ensure we run it with the correct MySQL binaries.
It adds additional safety checks for using the
Mysqld
type because it's reused between both the local MySQL interaction andmysqlctl
but also as a remote interface used fromvttablet
.This safety check means that we should never run certain things when running remotely inside
vttablet
, which is identified by thesocketFile
being set or not. When it is set, we now panic on certain actions we know are not going to work.By adding this panic we can ensure we catch uses like the restore usage earlier since it would break if we do anything unsupported.
Related Issue(s)
Fixes #13124
Checklist