Merge pull request #582 from pingcap/zimuxia/store-status
*: store global status variables to the db
This commit is contained in:
29
bootstrap.go
29
bootstrap.go
@ -92,6 +92,11 @@ const (
|
||||
CreateGloablVariablesTable = `CREATE TABLE if not exists mysql.GLOBAL_VARIABLES(
|
||||
VARIABLE_NAME VARCHAR(64) Not Null PRIMARY KEY,
|
||||
VARIABLE_VALUE VARCHAR(1024) DEFAULT Null);`
|
||||
// CreateGloablStatusTable is the SQL statement creates global status variable table in system db.
|
||||
// TODO: MySQL puts GLOBAL_STATUS table in INFORMATION_SCHEMA db.
|
||||
CreateGloablStatusTable = `CREATE TABLE if not exists mysql.GLOBAL_STATUS(
|
||||
VARIABLE_NAME VARCHAR(64) Not Null PRIMARY KEY,
|
||||
VARIABLE_VALUE VARCHAR(1024) DEFAULT Null);`
|
||||
// CreateTiDBTable is the SQL statement creates a table in system db.
|
||||
// This table is a key-value struct contains some information used by TiDB.
|
||||
// Currently we only put bootstrapped in it which indicates if the system is already bootstrapped.
|
||||
@ -134,7 +139,8 @@ func checkBootstrapped(s Session) (bool, error) {
|
||||
}
|
||||
|
||||
func checkBootstrappedVar(s Session) (bool, error) {
|
||||
sql := fmt.Sprintf(`SELECT VARIABLE_VALUE FROM %s.%s WHERE VARIABLE_NAME="%s"`, mysql.SystemDB, mysql.TiDBTable, bootstrappedVar)
|
||||
sql := fmt.Sprintf(`SELECT VARIABLE_VALUE FROM %s.%s WHERE VARIABLE_NAME="%s"`,
|
||||
mysql.SystemDB, mysql.TiDBTable, bootstrappedVar)
|
||||
rs, err := s.Execute(sql)
|
||||
if err != nil {
|
||||
if terror.TableNotExists.Equal(err) {
|
||||
@ -167,6 +173,8 @@ func doDDLWorks(s Session) {
|
||||
mustExecute(s, CreateColumnPrivTable)
|
||||
// Create global systemt variable table.
|
||||
mustExecute(s, CreateGloablVariablesTable)
|
||||
// Create global status variable table.
|
||||
mustExecute(s, CreateGloablStatusTable)
|
||||
// Create TiDB table.
|
||||
mustExecute(s, CreateTiDBTable)
|
||||
}
|
||||
@ -176,7 +184,8 @@ func doDDLWorks(s Session) {
|
||||
func doDMLWorks(s Session) {
|
||||
mustExecute(s, "BEGIN")
|
||||
// Insert a default user with empty password.
|
||||
mustExecute(s, `INSERT INTO mysql.user VALUES ("localhost", "root", "", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y"),
|
||||
mustExecute(s, `INSERT INTO mysql.user VALUES
|
||||
("localhost", "root", "", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y"),
|
||||
("127.0.0.1", "root", "", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y"),
|
||||
("::1", "root", "", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y");`)
|
||||
// Init global system variable table.
|
||||
@ -185,9 +194,21 @@ func doDMLWorks(s Session) {
|
||||
value := fmt.Sprintf(`("%s", "%s")`, strings.ToLower(k), v.Value)
|
||||
values = append(values, value)
|
||||
}
|
||||
sql := fmt.Sprintf("INSERT INTO %s.%s VALUES %s;", mysql.SystemDB, mysql.GlobalVariablesTable, strings.Join(values, ", "))
|
||||
sql := fmt.Sprintf("INSERT INTO %s.%s VALUES %s;", mysql.SystemDB, mysql.GlobalVariablesTable,
|
||||
strings.Join(values, ", "))
|
||||
mustExecute(s, sql)
|
||||
sql = fmt.Sprintf(`INSERT INTO %s.%s VALUES("%s", "%s", "Bootstrap flag. Do not delete.") ON DUPLICATE KEY UPDATE VARIABLE_VALUE="%s"`, mysql.SystemDB, mysql.TiDBTable, bootstrappedVar, bootstrappedVarTrue, bootstrappedVarTrue)
|
||||
// Init global status variable table.
|
||||
values = make([]string, 0, len(variable.StatusVars))
|
||||
for k, v := range variable.StatusVars {
|
||||
value := fmt.Sprintf(`("%s", "%s")`, strings.ToLower(k), v.Value)
|
||||
values = append(values, value)
|
||||
}
|
||||
sql = fmt.Sprintf("INSERT INTO %s.%s VALUES %s;", mysql.SystemDB, mysql.GlobalStatusTable,
|
||||
strings.Join(values, ", "))
|
||||
mustExecute(s, sql)
|
||||
sql = fmt.Sprintf(`INSERT INTO %s.%s VALUES("%s", "%s", "Bootstrap flag. Do not delete.")
|
||||
ON DUPLICATE KEY UPDATE VARIABLE_VALUE="%s"`,
|
||||
mysql.SystemDB, mysql.TiDBTable, bootstrappedVar, bootstrappedVarTrue, bootstrappedVarTrue)
|
||||
mustExecute(s, sql)
|
||||
mustExecute(s, "COMMIT")
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ func (d *ddl) CreateSchema(ctx context.Context, schema model.CIStr) (err error)
|
||||
|
||||
err = t.CreateDatabase(info)
|
||||
|
||||
log.Warnf("save schema %s", info)
|
||||
log.Warnf("save schema %v", info)
|
||||
return errors.Trace(err)
|
||||
})
|
||||
if d.onDDLChange != nil {
|
||||
|
||||
@ -130,6 +130,8 @@ const (
|
||||
ColumnPrivTable = "Columns_priv"
|
||||
// GlobalVariablesTable is the table contains global system variables.
|
||||
GlobalVariablesTable = "GLOBAL_VARIABLES"
|
||||
// GlobalStatusTable is the table contains global status variables.
|
||||
GlobalStatusTable = "GLOBAL_STATUS"
|
||||
// TiDBTable is the table contains tidb info.
|
||||
TiDBTable = "tidb"
|
||||
)
|
||||
|
||||
@ -44,16 +44,16 @@ type InfoSchemaPlan struct {
|
||||
}
|
||||
|
||||
var (
|
||||
schemataFields = buildResultFieldsForSchemata()
|
||||
tablesFields = buildResultFieldsForTables()
|
||||
columnsFields = buildResultFieldsForColumns()
|
||||
statisticsFields = buildResultFieldsForStatistics()
|
||||
characterSetsFields = buildResultFieldsForCharacterSets()
|
||||
characterSetsRecords = buildCharacterSetsRecords()
|
||||
collationsFields = buildResultFieldsForCollations()
|
||||
collationsRecords = buildColltionsRecords()
|
||||
filesFields = buildFilesFields()
|
||||
filesRecords = buildFilesRecords()
|
||||
schemataFields []*field.ResultField
|
||||
tablesFields []*field.ResultField
|
||||
columnsFields []*field.ResultField
|
||||
statisticsFields []*field.ResultField
|
||||
characterSetsFields []*field.ResultField
|
||||
collationsFields []*field.ResultField
|
||||
filesFields []*field.ResultField
|
||||
characterSetsRecords [][]interface{}
|
||||
collationsRecords [][]interface{}
|
||||
filesRecords [][]interface{}
|
||||
)
|
||||
|
||||
const (
|
||||
@ -512,3 +512,16 @@ func (isp *InfoSchemaPlan) Close() error {
|
||||
isp.cursor = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
schemataFields = buildResultFieldsForSchemata()
|
||||
tablesFields = buildResultFieldsForTables()
|
||||
columnsFields = buildResultFieldsForColumns()
|
||||
statisticsFields = buildResultFieldsForStatistics()
|
||||
characterSetsFields = buildResultFieldsForCharacterSets()
|
||||
collationsFields = buildResultFieldsForCollations()
|
||||
filesFields = buildFilesFields()
|
||||
characterSetsRecords = buildCharacterSetsRecords()
|
||||
collationsRecords = buildColltionsRecords()
|
||||
filesRecords = buildFilesRecords()
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ func (p *testInfoSchemaSuit) TestInfoSchema(c *C) {
|
||||
cnt = mustQuery(c, testDB, "select * from information_schema.columns")
|
||||
c.Assert(cnt, Greater, 0)
|
||||
cnt = mustQuery(c, testDB, "select * from information_schema.statistics")
|
||||
c.Assert(cnt, Equals, 16)
|
||||
c.Assert(cnt, Equals, 17)
|
||||
cnt = mustQuery(c, testDB, "select * from information_schema.character_sets")
|
||||
c.Assert(cnt, Greater, 0)
|
||||
cnt = mustQuery(c, testDB, "select * from information_schema.collations")
|
||||
|
||||
32
session.go
32
session.go
@ -295,30 +295,31 @@ func (s *session) getExecRet(ctx context.Context, sql string) (string, error) {
|
||||
|
||||
// GetGlobalStatusVar implements GlobalVarAccessor.GetGlobalStatusVar interface.
|
||||
func (s *session) GetGlobalStatusVar(ctx context.Context, name string) (string, error) {
|
||||
// TODO: get global status variables from store.
|
||||
v := variable.GetStatusVar(name)
|
||||
if v == nil {
|
||||
return "", terror.UnknownStatusVar.Gen("unknown status variable:%s", name)
|
||||
sql := fmt.Sprintf(`SELECT VARIABLE_VALUE FROM %s.%s WHERE VARIABLE_NAME="%s";`,
|
||||
mysql.SystemDB, mysql.GlobalStatusTable, name)
|
||||
statusVar, err := s.getExecRet(ctx, sql)
|
||||
if err != nil {
|
||||
if terror.ExecResultIsEmpty.Equal(err) {
|
||||
return "", terror.ExecResultIsEmpty.Gen("unknown status variable:%s", name)
|
||||
}
|
||||
return "", errors.Trace(err)
|
||||
}
|
||||
|
||||
return v.Value, nil
|
||||
return statusVar, nil
|
||||
}
|
||||
|
||||
// SetGlobalStatusVar implements GlobalVarAccessor.SetGlobalStatusVar interface.
|
||||
func (s *session) SetGlobalStatusVar(ctx context.Context, name string, value string) error {
|
||||
// TODO: set global status variables from store.
|
||||
v := variable.GetStatusVar(name)
|
||||
if v == nil {
|
||||
return terror.UnknownStatusVar.Gen("unknown status variable:%s", name)
|
||||
}
|
||||
v.Value = value
|
||||
|
||||
return nil
|
||||
sql := fmt.Sprintf(`UPDATE %s.%s SET VARIABLE_VALUE="%s" WHERE VARIABLE_NAME="%s";`,
|
||||
mysql.SystemDB, mysql.GlobalStatusTable, value, strings.ToLower(name))
|
||||
_, err := s.ExecRestrictedSQL(ctx, sql)
|
||||
return errors.Trace(err)
|
||||
}
|
||||
|
||||
// GetGlobalSysVar implements GlobalVarAccessor.GetGlobalSysVar interface.
|
||||
func (s *session) GetGlobalSysVar(ctx context.Context, name string) (string, error) {
|
||||
sql := fmt.Sprintf(`SELECT VARIABLE_VALUE FROM %s.%s WHERE VARIABLE_NAME="%s";`, mysql.SystemDB, mysql.GlobalVariablesTable, name)
|
||||
sql := fmt.Sprintf(`SELECT VARIABLE_VALUE FROM %s.%s WHERE VARIABLE_NAME="%s";`,
|
||||
mysql.SystemDB, mysql.GlobalVariablesTable, name)
|
||||
sysVar, err := s.getExecRet(ctx, sql)
|
||||
if err != nil {
|
||||
if terror.ExecResultIsEmpty.Equal(err) {
|
||||
@ -332,7 +333,8 @@ func (s *session) GetGlobalSysVar(ctx context.Context, name string) (string, err
|
||||
|
||||
// SetGlobalSysVar implements GlobalVarAccessor.SetGlobalSysVar interface.
|
||||
func (s *session) SetGlobalSysVar(ctx context.Context, name string, value string) error {
|
||||
sql := fmt.Sprintf(`UPDATE %s.%s SET VARIABLE_VALUE="%s" WHERE VARIABLE_NAME="%s";`, mysql.SystemDB, mysql.GlobalVariablesTable, value, strings.ToLower(name))
|
||||
sql := fmt.Sprintf(`UPDATE %s.%s SET VARIABLE_VALUE="%s" WHERE VARIABLE_NAME="%s";`,
|
||||
mysql.SystemDB, mysql.GlobalVariablesTable, value, strings.ToLower(name))
|
||||
_, err := s.ExecRestrictedSQL(ctx, sql)
|
||||
return errors.Trace(err)
|
||||
}
|
||||
|
||||
@ -1072,11 +1072,16 @@ func (s *testSessionSuite) TestBootstrapWithError(c *C) {
|
||||
mustExecSQL(c, se, "SELECT * from mysql.db;")
|
||||
mustExecSQL(c, se, "SELECT * from mysql.tables_priv;")
|
||||
mustExecSQL(c, se, "SELECT * from mysql.columns_priv;")
|
||||
// Check privilege tables.
|
||||
// Check global variables.
|
||||
r = mustExecSQL(c, se, "SELECT COUNT(*) from mysql.global_variables;")
|
||||
v, err := r.FirstRow()
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(v[0], Equals, int64(len(variable.SysVars)))
|
||||
// Check global status.
|
||||
r = mustExecSQL(c, se, "SELECT COUNT(*) from mysql.global_status;")
|
||||
v, err = r.FirstRow()
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(v[0], Equals, int64(len(variable.StatusVars)))
|
||||
r = mustExecSQL(c, se, `SELECT VARIABLE_VALUE from mysql.TiDB where VARIABLE_NAME="bootstrapped";`)
|
||||
row, err = r.Next()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
Reference in New Issue
Block a user