Skip to content
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

Update the embedded config data in mysqlctl #10094

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ export CGO_CFLAGS := -O1

# regenerate rice-box.go when any of the .cnf files change
embed_config:
cd go/vt/mysqlctl && go run github.com/GeertJohan/go.rice/rice embed-go
cd go/vt/mysqlctl && go build .
cd go/vt/mysqlctl && go run github.com/GeertJohan/go.rice/rice embed-go && go build .

# build the vitess binaries with dynamic dependency on libc
build-dyn:
Expand Down
11 changes: 10 additions & 1 deletion config/init_db.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
# Equivalent of mysql_secure_installation
###############################################################################

# We need to ensure that super_read_only is disabled so that we can execute
# these commands. Note that disabling it does NOT disable read_only.
# We save the current value so that we only re-enable it at the end if it was
# enabled before.
SET @original_super_read_only=IF(@@global.super_read_only=1, 'ON', 'OFF');
SET GLOBAL super_read_only='OFF';

# Changes during the init db should not make it to the binlog.
# They could potentially create errant transactions on replicas.
SET sql_log_bin = 0;
Expand Down Expand Up @@ -63,7 +70,6 @@ CREATE USER 'vt_appdebug'@'localhost';
GRANT SELECT, SHOW DATABASES, PROCESS ON *.* TO 'vt_appdebug'@'localhost';

# User for administrative operations that need to be executed as non-SUPER.
# Same permissions as vt_app here.
CREATE USER 'vt_allprivs'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE,
REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES,
Expand Down Expand Up @@ -101,3 +107,6 @@ FLUSH PRIVILEGES;

RESET SLAVE ALL;
RESET MASTER;

# We need to set super_read_only back to what it was before
SET GLOBAL super_read_only=IFNULL(@original_super_read_only, 'OFF');
4 changes: 2 additions & 2 deletions go/cmd/vtbackup/vtbackup.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,13 +271,13 @@ func takeBackup(ctx context.Context, topoServer *topo.Server, backupStorage back
}
cmds := mysqlctl.CreateReparentJournal()
cmds = append(cmds, fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", sqlescape.EscapeID(dbName)))
if err := mysqld.ExecuteSuperQueryList(ctx, cmds); err != nil {
if err := mysqld.ExecuteSuperQueryListWithReadOnlyHandling(ctx, cmds); err != nil {
return fmt.Errorf("can't initialize database: %v", err)
}

// Execute Alter commands on reparent_journal and ignore errors
cmds = mysqlctl.AlterReparentJournal()
_ = mysqld.ExecuteSuperQueryList(ctx, cmds)
_ = mysqld.ExecuteSuperQueryListWithReadOnlyHandling(ctx, cmds)

backupParams.BackupTime = time.Now()
// Now we're ready to take the backup.
Expand Down
26 changes: 26 additions & 0 deletions go/mysql/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,32 @@ func (c *Conn) ExecuteFetch(query string, maxrows int, wantfields bool) (result
return result, err
}

// ExecuteFetchWithReadOnlyHandling should be used if you are executing a write query
// on a tablet that may NOT be a primary and you want to execute it regardless of
// tablet type. This function will temporarily make the mysql instance read-write and
// re-enable read-only mode after the query is executed if needed.
func (c *Conn) ExecuteFetchWithReadOnlyHandling(query string, maxrows int, wantfields bool) (result *sqltypes.Result, err error) {
// Note: MariaDB does not have super_read_only but support for it is EOL in v14.0+
if !c.IsMariaDB() {
if err := c.WriteComQuery("SELECT @@global.super_read_only"); err != nil {
return nil, err
}
res, _, _, err := c.ReadQueryResult(1, false)
if err == nil && len(res.Rows) == 1 {
sro := res.Rows[0][0].ToString()
if sro == "1" || sro == "ON" {
defer c.WriteComQuery("SET GLOBAL super_read_only='ON'")
if err = c.WriteComQuery("SET GLOBAL super_read_only='OFF'"); err != nil {
return nil, err
}
}
}
}

result, _, err = c.ExecuteFetchMulti(query, maxrows, wantfields)
return result, err
}

// ExecuteFetchMulti is for fetching multiple results from a multi-statement result.
// It returns an additional 'more' flag. If it is set, you must fetch the additional
// results using ReadQueryResult.
Expand Down
2 changes: 1 addition & 1 deletion go/test/endtoend/cluster/vttablet_process.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ func executeQuery(dbConn *mysql.Conn, query string) (*sqltypes.Result, error) {
retryDelay := 1 * time.Second
for i := 1; i <= retries; i++ {
log.Infof("Executing query %s on %s (attempt %d of %d)", query, i, retries)
result, err = dbConn.ExecuteFetch(query, 10000, true)
result, err = dbConn.ExecuteFetchWithReadOnlyHandling(query, 10000, true)
if err == nil {
break
}
Expand Down
6 changes: 6 additions & 0 deletions go/test/endtoend/sharding/initialsharding/sharding_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,8 @@ func writeInitDBFile() {
sql := string(initDb)
newInitDbFile = path.Join(ClusterInstance.TmpDirectory, "init_db_with_passwords.sql")
sql = sql + GetPasswordUpdateSQL(ClusterInstance) + `
SET @original_super_read_only=IF(@@global.super_read_only=1, 'ON', 'OFF');
SET GLOBAL super_read_only=OFF;
# connecting through a port requires 127.0.0.1
# --host=localhost will connect through socket
CREATE USER 'vt_dba'@'127.0.0.1' IDENTIFIED BY 'VtDbaPass';
Expand Down Expand Up @@ -664,6 +666,7 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE,
SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER
ON *.* TO 'vt_filtered'@'127.0.0.1';
FLUSH PRIVILEGES;
SET GLOBAL super_read_only=IFNULL(@original_super_read_only, 'OFF');
`
os.WriteFile(newInitDbFile, []byte(sql), 0666)

Expand All @@ -686,6 +689,8 @@ func WriteDbCredentialToTmp(tmpDir string) string {
// GetPasswordUpdateSQL returns the sql for password update
func GetPasswordUpdateSQL(localCluster *cluster.LocalProcessCluster) string {
pwdChangeCmd := `
SET @original_super_read_only=IF(@@global.super_read_only=1, 'ON', 'OFF');
SET GLOBAL super_read_only=OFF;
# Set real passwords for all users.
UPDATE mysql.user SET %s = PASSWORD('RootPass')
WHERE User = 'root' AND Host = 'localhost';
Expand All @@ -700,6 +705,7 @@ func GetPasswordUpdateSQL(localCluster *cluster.LocalProcessCluster) string {
UPDATE mysql.user SET %s = PASSWORD('VtFilteredPass')
WHERE User = 'vt_filtered' AND Host = 'localhost';
FLUSH PRIVILEGES;
SET GLOBAL super_read_only=IFNULL(@original_super_read_only, 'OFF');
`
pwdCol, _ := getPasswordField(localCluster)
return fmt.Sprintf(pwdChangeCmd, pwdCol, pwdCol, pwdCol, pwdCol, pwdCol, pwdCol)
Expand Down
13 changes: 3 additions & 10 deletions go/test/endtoend/tabletmanager/tablet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"vitess.io/vitess/go/test/endtoend/cluster"
Expand All @@ -42,17 +41,11 @@ func TestEnsureDB(t *testing.T) {
err = clusterInstance.StartVttablet(tablet, "NOT_SERVING", false, cell, "dbtest", hostname, "0")
require.NoError(t, err)

// Make it the primary.
// Make it the primary, which should create the DB
err = clusterInstance.VtctlclientProcess.ExecuteCommand("TabletExternallyReparented", tablet.Alias)
require.EqualError(t, err, "exit status 1")

// It is still NOT_SERVING because the db is read-only.
assert.Equal(t, "NOT_SERVING", tablet.VttabletProcess.GetTabletStatus())
status := tablet.VttabletProcess.GetStatusDetails()
assert.Contains(t, status, "read-only")
require.NoError(t, err)

// Switch to read-write and verify that that we go serving.
_ = clusterInstance.VtctlclientProcess.ExecuteCommand("SetReadWrite", tablet.Alias)
// verify that that we are serving
err = tablet.VttabletProcess.WaitForTabletStatus("SERVING")
require.NoError(t, err)
killTablets(t, tablet)
Expand Down
7 changes: 6 additions & 1 deletion go/test/endtoend/utils/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,12 @@ func createInitSQLFile(mysqlDir, ksName string) (string, error) {
}
defer f.Close()

_, err = f.WriteString(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s;", ksName))
sql := fmt.Sprintf(`
SET @original_super_read_only=IF(@@global.super_read_only=1, 'ON', 'OFF');
SET GLOBAL super_read_only='OFF';
CREATE DATABASE IF NOT EXISTS %s;
SET GLOBAL super_read_only=IFNULL(@original_super_read_only, 'OFF');`, ksName)
_, err = f.WriteString(sql)
if err != nil {
return "", err
}
Expand Down
18 changes: 9 additions & 9 deletions go/vt/mysqlctl/metadata_tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (m *MetadataManager) UpsertLocalMetadata(mysqld MysqlDaemon, localMetadata
}

func createMetadataTables(conn *dbconnpool.DBConnection, dbName string) error {
if _, err := conn.ExecuteFetch("CREATE DATABASE IF NOT EXISTS _vt", 0, false); err != nil {
if _, err := conn.ExecuteFetchWithReadOnlyHandling("CREATE DATABASE IF NOT EXISTS _vt", 0, false); err != nil {
return err
}

Expand All @@ -147,12 +147,12 @@ func createMetadataTables(conn *dbconnpool.DBConnection, dbName string) error {
}

func createLocalMetadataTable(conn *dbconnpool.DBConnection, dbName string) error {
if _, err := conn.ExecuteFetch(sqlCreateLocalMetadataTable, 0, false); err != nil {
if _, err := conn.ExecuteFetchWithReadOnlyHandling(sqlCreateLocalMetadataTable, 0, false); err != nil {
return err
}

for _, sql := range sqlAlterLocalMetadataTable {
if _, err := conn.ExecuteFetch(sql, 0, false); err != nil {
if _, err := conn.ExecuteFetchWithReadOnlyHandling(sql, 0, false); err != nil {
// Ignore "Duplicate column name 'db_name'" errors which can happen on every restart.
if merr, ok := err.(*mysql.SQLError); !ok || merr.Num != mysql.ERDupFieldName {
log.Errorf("Error executing %v: %v", sql, err)
Expand All @@ -162,20 +162,20 @@ func createLocalMetadataTable(conn *dbconnpool.DBConnection, dbName string) erro
}

sql := fmt.Sprintf(sqlUpdateLocalMetadataTable, dbName)
if _, err := conn.ExecuteFetch(sql, 0, false); err != nil {
if _, err := conn.ExecuteFetchWithReadOnlyHandling(sql, 0, false); err != nil {
log.Errorf("Error executing %v: %v, continuing. Please check the data in _vt.local_metadata and take corrective action.", sql, err)
}

return nil
}

func createShardMetadataTable(conn *dbconnpool.DBConnection, dbName string) error {
if _, err := conn.ExecuteFetch(sqlCreateShardMetadataTable, 0, false); err != nil {
if _, err := conn.ExecuteFetchWithReadOnlyHandling(sqlCreateShardMetadataTable, 0, false); err != nil {
return err
}

for _, sql := range sqlAlterShardMetadataTable {
if _, err := conn.ExecuteFetch(sql, 0, false); err != nil {
if _, err := conn.ExecuteFetchWithReadOnlyHandling(sql, 0, false); err != nil {
// Ignore "Duplicate column name 'db_name'" errors which can happen on every restart.
if merr, ok := err.(*mysql.SQLError); !ok || merr.Num != mysql.ERDupFieldName {
log.Errorf("Error executing %v: %v", sql, err)
Expand All @@ -185,7 +185,7 @@ func createShardMetadataTable(conn *dbconnpool.DBConnection, dbName string) erro
}

sql := fmt.Sprintf(sqlUpdateShardMetadataTable, dbName)
if _, err := conn.ExecuteFetch(sql, 0, false); err != nil {
if _, err := conn.ExecuteFetchWithReadOnlyHandling(sql, 0, false); err != nil {
log.Errorf("Error executing %v: %v, continuing. Please check the data in _vt.shard_metadata and take corrective action.", sql, err)
}

Expand Down Expand Up @@ -221,12 +221,12 @@ func upsertLocalMetadata(conn *dbconnpool.DBConnection, localMetadata map[string
queryBuf.WriteString(") ON DUPLICATE KEY UPDATE value = ")
valValue.EncodeSQL(&queryBuf)

if _, err := conn.ExecuteFetch(queryBuf.String(), 0, false); err != nil {
if _, err := conn.ExecuteFetchWithReadOnlyHandling(queryBuf.String(), 0, false); err != nil {
return err
}
}

if _, err := conn.ExecuteFetch("COMMIT", 0, false); err != nil {
if _, err := conn.ExecuteFetchWithReadOnlyHandling("COMMIT", 0, false); err != nil {
return err
}

Expand Down
19 changes: 19 additions & 0 deletions go/vt/mysqlctl/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@ func (mysqld *Mysqld) ExecuteSuperQuery(ctx context.Context, query string) error
return mysqld.ExecuteSuperQueryList(ctx, []string{query})
}

// ExecuteSuperQueryListWithReadOnlyHandling allows the user to execute queries as a super user
// even if the instance is in read-only mode. It will temporarily switch the instance to read-write
// before executing the queries and put the instance back in its original state afterward.
func (mysqld *Mysqld) ExecuteSuperQueryListWithReadOnlyHandling(ctx context.Context, queryList []string) error {
conn, err := getPoolReconnect(ctx, mysqld.dbaPool)
if err != nil {
return err
}
defer conn.Recycle()

sroql := make([]string, 0, len(queryList)+3)
sroql[0] = "SET @original_super_read_only=IF(@@global.super_read_only=1, 'ON', 'OFF')"
sroql[1] = "SET GLOBAL super_read_only='OFF'"
sroql = append(sroql, queryList...)
sroql[len(sroql)-1] = "SET GLOBAL super_read_only=IFNULL(@original_super_read_only, 'OFF')"

return mysqld.executeSuperQueryListConn(ctx, conn, sroql)
}

// ExecuteSuperQueryList alows the user to execute queries as a super user.
func (mysqld *Mysqld) ExecuteSuperQueryList(ctx context.Context, queryList []string) error {
conn, err := getPoolReconnect(ctx, mysqld.dbaPool)
Expand Down
Loading