Start mysqld for mysql_upgrade with --skip-grant-tables and --skip-networking.

When mysqld is started on a database from an older version (the only use case
when mysql_upgrade will do anything and is really necessary) it may fail to
start due to mysql.* tables having old structure. --skip-grant-tables will
ensure that mysqld doesn't try to read mysql.* tables before mysql_upgrade fixed
their structure. Since anyone can connect to mysqld without password when it's
started with --skip-grant-tables, we should also pass --skip-networking to it.

To make passing those flags to mysqld possible I'm extending notion of
mysqld_start hook to accept list of any arguments that should be passed to
mysqld.
This commit is contained in:
Pavel Ivanov 2016-07-25 09:33:06 -07:00
Родитель 973f5e19a7
Коммит 88e607da13
8 изменённых файлов: 26 добавлений и 12 удалений

Просмотреть файл

@ -13,6 +13,7 @@ import (
log "github.com/golang/glog"
"github.com/youtube/vitess/go/exit"
"github.com/youtube/vitess/go/flagutil"
"github.com/youtube/vitess/go/netutil"
"github.com/youtube/vitess/go/vt/dbconfigs"
"github.com/youtube/vitess/go/vt/logutil"
@ -93,6 +94,8 @@ func shutdownCmd(subFlags *flag.FlagSet, args []string) error {
func startCmd(subFlags *flag.FlagSet, args []string) error {
waitTime := subFlags.Duration("wait_time", 5*time.Minute, "how long to wait for startup")
var mysqldArgs flagutil.StringListValue
subFlags.Var(&mysqldArgs, "mysqld_args", "List of comma-separated flags to pass additionally to mysqld")
subFlags.Parse(args)
// There ought to be an existing my.cnf, so use it to find mysqld.
@ -104,7 +107,7 @@ func startCmd(subFlags *flag.FlagSet, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), *waitTime)
defer cancel()
if err := mysqld.Start(ctx); err != nil {
if err := mysqld.Start(ctx, mysqldArgs...); err != nil {
return fmt.Errorf("failed start mysql: %v", err)
}
return nil

Просмотреть файл

@ -654,8 +654,14 @@ func Restore(ctx context.Context, mysqld MysqlDaemon, dir string, restoreConcurr
}
// mysqld needs to be running in order for mysql_upgrade to work.
// If we've just restored from a backup from previous MySQL version then mysqld
// may fail to start due to a different structure of mysql.* tables. The flag
// --skip-grant-tables ensures that these tables are not read until mysql_upgrade
// is executed. And since with --skip-grant-tables anyone can connect to MySQL
// without password, we are passing --skip-networking to greatly reduce the set
// of those who can connect.
logger.Infof("Restore: starting mysqld for mysql_upgrade")
err = mysqld.Start(ctx)
err = mysqld.Start(ctx, "--skip-grant-tables", "--skip-networking")
if err != nil {
return replication.Position{}, err
}

Просмотреть файл

@ -41,8 +41,10 @@ func factory(network, addr string, dialTimeout time.Duration) (mysqlctlclient.My
}
// Start is part of the MysqlctlClient interface.
func (c *client) Start(ctx context.Context) error {
_, err := c.c.Start(ctx, &mysqlctlpb.StartRequest{})
func (c *client) Start(ctx context.Context, mysqldArgs ...string) error {
_, err := c.c.Start(ctx, &mysqlctlpb.StartRequest{
MysqldArgs: mysqldArgs,
})
return err
}

Просмотреть файл

@ -24,7 +24,7 @@ type server struct {
// Start implements the server side of the MysqlctlClient interface.
func (s *server) Start(ctx context.Context, request *mysqlctlpb.StartRequest) (*mysqlctlpb.StartResponse, error) {
return &mysqlctlpb.StartResponse{}, s.mysqld.Start(ctx)
return &mysqlctlpb.StartResponse{}, s.mysqld.Start(ctx, request.MysqldArgs...)
}
// Shutdown implements the server side of the MysqlctlClient interface.

Просмотреть файл

@ -29,7 +29,7 @@ type MysqlDaemon interface {
TabletDir() string
// methods related to mysql running or not
Start(ctx context.Context) error
Start(ctx context.Context, mysqldArgs ...string) error
Shutdown(ctx context.Context, waitForMysqld bool) error
RunMysqlUpgrade() error
ReinitConfig(ctx context.Context) error
@ -229,7 +229,7 @@ func (fmd *FakeMysqlDaemon) TabletDir() string {
}
// Start is part of the MysqlDaemon interface
func (fmd *FakeMysqlDaemon) Start(ctx context.Context) error {
func (fmd *FakeMysqlDaemon) Start(ctx context.Context, mysqldArgs ...string) error {
if fmd.Running {
return fmt.Errorf("fake mysql daemon already running")
}

Просмотреть файл

@ -21,7 +21,7 @@ var connectionTimeout = flag.Duration("mysqlctl_client_connection_timeout", 30*t
// MysqlctlClient defines the interface used to send remote mysqlctl commands
type MysqlctlClient interface {
// Start calls Mysqld.Start remotely.
Start(ctx context.Context) error
Start(ctx context.Context, mysqldArgs ...string) error
// Shutdown calls Mysqld.Shutdown remotely.
Shutdown(ctx context.Context, waitForMysqld bool) error

Просмотреть файл

@ -169,7 +169,7 @@ func (mysqld *Mysqld) RunMysqlUpgrade() error {
// Start will start the mysql daemon, either by running the 'mysqld_start'
// hook, or by running mysqld_safe in the background.
// If a mysqlctld address is provided in a flag, Start will run remotely.
func (mysqld *Mysqld) Start(ctx context.Context) error {
func (mysqld *Mysqld) Start(ctx context.Context, mysqldArgs ...string) error {
// Execute as remote action on mysqlctld if requested.
if *socketFile != "" {
log.Infof("executing Mysqld.Start() remotely via mysqlctld server: %v", *socketFile)
@ -178,14 +178,14 @@ func (mysqld *Mysqld) Start(ctx context.Context) error {
return fmt.Errorf("can't dial mysqlctld: %v", err)
}
defer client.Close()
return client.Start(ctx)
return client.Start(ctx, mysqldArgs...)
}
var name string
ts := fmt.Sprintf("Mysqld.Start(%v)", time.Now().Unix())
// try the mysqld start hook, if any
switch hr := hook.NewSimpleHook("mysqld_start").Execute(); hr.ExitStatus {
switch hr := hook.NewHook("mysqld_start", mysqldArgs).Execute(); hr.ExitStatus {
case hook.HOOK_SUCCESS:
// hook exists and worked, we can keep going
name = "mysqld_start hook"
@ -202,6 +202,7 @@ func (mysqld *Mysqld) Start(ctx context.Context) error {
}
arg := []string{
"--defaults-file=" + mysqld.config.path}
arg = append(arg, mysqldArgs...)
env := []string{os.ExpandEnv("LD_LIBRARY_PATH=$VT_MYSQL_ROOT/lib/mysql")}
cmd := exec.Command(name, arg...)

Просмотреть файл

@ -5,7 +5,9 @@ syntax = "proto3";
package mysqlctl;
message StartRequest{}
message StartRequest{
repeated string mysqld_args = 1;
}
message StartResponse{}