Skip to content

Commit

Permalink
session, variable: move gc special sysvars to getters/setters (#24896)
Browse files Browse the repository at this point in the history
  • Loading branch information
morgo authored Aug 18, 2021
1 parent ef59ede commit 79f0b49
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 161 deletions.
155 changes: 18 additions & 137 deletions session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,8 @@ var (
sessionExecuteParseDurationGeneral = metrics.SessionExecuteParseDuration.WithLabelValues(metrics.LblGeneral)

telemetryCTEUsage = metrics.TelemetrySQLCTECnt

tiKVGCAutoConcurrency = "tikv_gc_auto_concurrency"
)

var gcVariableMap = map[string]string{
variable.TiDBGCRunInterval: "tikv_gc_run_interval",
variable.TiDBGCLifetime: "tikv_gc_life_time",
variable.TiDBGCConcurrency: "tikv_gc_concurrency",
variable.TiDBGCEnable: "tikv_gc_enable",
variable.TiDBGCScanLockMode: "tikv_gc_scan_lock_mode",
}

// Session context, it is consistent with the lifecycle of a client connection.
type Session interface {
sessionctx.Context
Expand Down Expand Up @@ -1075,27 +1065,10 @@ func (s *session) getTableValue(ctx context.Context, tblName string, varName str
return value, nil
}

var gcVariableComments = map[string]string{
variable.TiDBGCRunInterval: "GC run interval, at least 10m, in Go format.",
variable.TiDBGCLifetime: "All versions within life time will not be collected by GC, at least 10m, in Go format.",
variable.TiDBGCConcurrency: "How many goroutines used to do GC parallel, [1, 128], default 2",
variable.TiDBGCEnable: "Current GC enable status",
tiKVGCAutoConcurrency: "Let TiDB pick the concurrency automatically. If set false, tikv_gc_concurrency will be used",
variable.TiDBGCScanLockMode: "Mode of scanning locks, \"physical\" or \"legacy\"",
}

// replaceTableValue executes restricted sql updates the variable value
func (s *session) replaceTableValue(ctx context.Context, tblName string, varName, val string) error {
if tblName == mysql.TiDBTable { // maintain comment metadata
comment := gcVariableComments[varName]
stmt, err := s.ParseWithParams(ctx, `REPLACE INTO %n.%n (variable_name, variable_value, comment) VALUES (%?, %?, %?)`, mysql.SystemDB, tblName, varName, val, comment)
if err != nil {
return err
}
_, _, err = s.ExecRestrictedStmt(ctx, stmt)
return err
}
stmt, err := s.ParseWithParams(ctx, `REPLACE INTO %n.%n (variable_name, variable_value) VALUES (%?, %?)`, mysql.SystemDB, tblName, varName, val)
// replaceGlobalVariablesTableValue executes restricted sql updates the variable value
// It will then notify the etcd channel that the value has changed.
func (s *session) replaceGlobalVariablesTableValue(ctx context.Context, varName, val string) error {
stmt, err := s.ParseWithParams(ctx, `REPLACE INTO %n.%n (variable_name, variable_value) VALUES (%?, %?)`, mysql.SystemDB, mysql.GlobalVariablesTable, varName, val)
if err != nil {
return err
}
Expand All @@ -1104,19 +1077,8 @@ func (s *session) replaceTableValue(ctx context.Context, tblName string, varName
return err
}

func (s *session) varFromTiDBTable(name string) bool {
switch name {
case variable.TiDBGCConcurrency, variable.TiDBGCEnable, variable.TiDBGCRunInterval, variable.TiDBGCLifetime, variable.TiDBGCScanLockMode:
return true
}
return false
}

// GetGlobalSysVar implements GlobalVarAccessor.GetGlobalSysVar interface.
func (s *session) GetGlobalSysVar(name string) (string, error) {
if name == variable.TiDBSlowLogMasking {
name = variable.TiDBRedactLog
}
if s.Value(sessionctx.Initing) != nil {
// When running bootstrap or upgrade, we should not access global storage.
return "", nil
Expand All @@ -1143,10 +1105,6 @@ func (s *session) GetGlobalSysVar(name string) (string, error) {
return sv.Value, nil
}
}
// Fetch mysql.tidb values if required
if s.varFromTiDBTable(name) {
return s.getTiDBTableValue(name, sysVar)
}
return sysVar, nil
}

Expand All @@ -1162,8 +1120,7 @@ func (s *session) SetGlobalSysVar(name, value string) (err error) {
if err = sv.SetGlobalFromHook(s.sessionVars, value, false); err != nil {
return err
}

return s.updateGlobalSysVar(sv, value)
return s.replaceGlobalVariablesTableValue(context.TODO(), sv.Name, value)
}

// SetGlobalSysVarOnly updates the sysvar, but does not call the validation function or update aliases.
Expand All @@ -1176,93 +1133,22 @@ func (s *session) SetGlobalSysVarOnly(name, value string) (err error) {
if err = sv.SetGlobalFromHook(s.sessionVars, value, true); err != nil {
return err
}
return s.updateGlobalSysVar(sv, value)
}

func (s *session) updateGlobalSysVar(sv *variable.SysVar, value string) error {
// update mysql.tidb if required.
if s.varFromTiDBTable(sv.Name) {
if err := s.setTiDBTableValue(sv.Name, value); err != nil {
return err
}
}
return s.replaceTableValue(context.TODO(), mysql.GlobalVariablesTable, sv.Name, value)
return s.replaceGlobalVariablesTableValue(context.TODO(), sv.Name, value)
}

// setTiDBTableValue handles tikv_* sysvars which need to update mysql.tidb
// for backwards compatibility. Validation has already been performed.
func (s *session) setTiDBTableValue(name, val string) error {
if name == variable.TiDBGCConcurrency {
autoConcurrency := "false"
if val == "-1" {
autoConcurrency = "true"
}
err := s.replaceTableValue(context.TODO(), mysql.TiDBTable, tiKVGCAutoConcurrency, autoConcurrency)
if err != nil {
return err
}
// SetTiDBTableValue implements GlobalVarAccessor.SetTiDBTableValue interface.
func (s *session) SetTiDBTableValue(name, value, comment string) error {
stmt, err := s.ParseWithParams(context.TODO(), `REPLACE INTO mysql.tidb (variable_name, variable_value, comment) VALUES (%?, %?, %?)`, name, value, comment)
if err != nil {
return err
}
val = onOffToTrueFalse(val)
err := s.replaceTableValue(context.TODO(), mysql.TiDBTable, gcVariableMap[name], val)
_, _, err = s.ExecRestrictedStmt(context.TODO(), stmt)
return err
}

// In mysql.tidb the convention has been to store the string value "true"/"false",
// but sysvars use the convention ON/OFF.
func trueFalseToOnOff(str string) string {
if strings.EqualFold("true", str) {
return variable.On
} else if strings.EqualFold("false", str) {
return variable.Off
}
return str
}

// In mysql.tidb the convention has been to store the string value "true"/"false",
// but sysvars use the convention ON/OFF.
func onOffToTrueFalse(str string) string {
if strings.EqualFold("ON", str) {
return "true"
} else if strings.EqualFold("OFF", str) {
return "false"
}
return str
}

// getTiDBTableValue handles tikv_* sysvars which need
// to read from mysql.tidb for backwards compatibility.
func (s *session) getTiDBTableValue(name, val string) (string, error) {
if name == variable.TiDBGCConcurrency {
// Check if autoconcurrency is set
autoConcurrencyVal, err := s.getTableValue(context.TODO(), mysql.TiDBTable, tiKVGCAutoConcurrency)
if err == nil && strings.EqualFold(autoConcurrencyVal, "true") {
return "-1", nil // convention for "AUTO"
}
}
tblValue, err := s.getTableValue(context.TODO(), mysql.TiDBTable, gcVariableMap[name])
if err != nil {
return val, nil // mysql.tidb value does not exist.
}
// Run validation on the tblValue. This will return an error if it can't be validated,
// but will also make it more consistent: disTribuTeD -> DISTRIBUTED etc
tblValue = trueFalseToOnOff(tblValue)
validatedVal, err := variable.GetSysVar(name).Validate(s.sessionVars, tblValue, variable.ScopeGlobal)
if err != nil {
logutil.Logger(context.Background()).Warn("restoring sysvar value since validating mysql.tidb value failed",
zap.Error(err),
zap.String("name", name),
zap.String("tblName", gcVariableMap[name]),
zap.String("tblValue", tblValue),
zap.String("restoredValue", val))
err = s.replaceTableValue(context.TODO(), mysql.TiDBTable, gcVariableMap[name], val)
return val, err
}
if validatedVal != val {
// The sysvar value is out of sync.
err = s.replaceTableValue(context.TODO(), mysql.GlobalVariablesTable, gcVariableMap[name], validatedVal)
return validatedVal, err
}
return validatedVal, nil
// GetTiDBTableValue implements GlobalVarAccessor.GetTiDBTableValue interface.
func (s *session) GetTiDBTableValue(name string) (string, error) {
return s.getTableValue(context.TODO(), mysql.TiDBTable, name)
}

var _ sqlexec.SQLParser = &session{}
Expand Down Expand Up @@ -2459,7 +2345,7 @@ func CreateSessionWithOpt(store kv.Storage, opt *Opt) (Session, error) {

// loadCollationParameter loads collation parameter from mysql.tidb
func loadCollationParameter(se *session) (bool, error) {
para, err := loadParameter(se, tidbNewCollationEnabled)
para, err := se.getTableValue(context.TODO(), mysql.TiDBTable, tidbNewCollationEnabled)
if err != nil {
return false, err
}
Expand All @@ -2480,7 +2366,7 @@ func loadCollationParameter(se *session) (bool, error) {
// version is v4.0.9.
// See the comment upon the function `upgradeToVer54` for details.
func loadDefMemQuotaQuery(se *session) (int64, error) {
_, err := loadParameter(se, tidbDefMemoryQuotaQuery)
_, err := se.getTableValue(context.TODO(), mysql.TiDBTable, tidbDefMemoryQuotaQuery)
if err != nil {
if err == errResultIsEmpty {
return 1 << 30, nil
Expand All @@ -2492,7 +2378,7 @@ func loadDefMemQuotaQuery(se *session) (int64, error) {
}

func loadDefOOMAction(se *session) (string, error) {
defOOMAction, err := loadParameter(se, tidbDefOOMAction)
defOOMAction, err := se.getTableValue(context.TODO(), mysql.TiDBTable, tidbDefOOMAction)
if err != nil {
if err == errResultIsEmpty {
return config.GetGlobalConfig().OOMAction, nil
Expand All @@ -2510,11 +2396,6 @@ var (
errResultIsEmpty = dbterror.ClassExecutor.NewStd(errno.ErrResultIsEmpty)
)

// loadParameter loads read-only parameter from mysql.tidb
func loadParameter(se *session, name string) (string, error) {
return se.getTableValue(context.TODO(), mysql.TiDBTable, name)
}

// BootstrapSession runs the first time when the TiDB server start.
func BootstrapSession(store kv.Storage) (*domain.Domain, error) {
cfg := config.GetGlobalConfig()
Expand Down
10 changes: 10 additions & 0 deletions sessionctx/variable/mock_globalaccessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,13 @@ func (m *MockGlobalAccessor) SetGlobalSysVar(name string, value string) error {
func (m *MockGlobalAccessor) SetGlobalSysVarOnly(name string, value string) error {
panic("not supported")
}

// GetTiDBTableValue implements GlobalVarAccessor.GetTiDBTableValue interface.
func (m *MockGlobalAccessor) GetTiDBTableValue(name string) (string, error) {
panic("not supported")
}

// SetTiDBTableValue implements GlobalVarAccessor.SetTiDBTableValue interface.
func (m *MockGlobalAccessor) SetTiDBTableValue(name, value, comment string) error {
panic("not supported")
}
13 changes: 0 additions & 13 deletions sessionctx/variable/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -1616,19 +1616,6 @@ func (s *SessionVars) GetTemporaryTable(tblInfo *model.TableInfo) tableutil.Temp
return nil
}

// special session variables.
const (
SQLModeVar = "sql_mode"
CharacterSetResults = "character_set_results"
MaxAllowedPacket = "max_allowed_packet"
TimeZone = "time_zone"
TxnIsolation = "tx_isolation"
TransactionIsolation = "transaction_isolation"
TxnIsolationOneShot = "tx_isolation_one_shot"
MaxExecutionTime = "max_execution_time"
ReadOnly = "read_only"
)

// TableDelta stands for the changed count for one table or partition.
type TableDelta struct {
Delta int64
Expand Down
Loading

0 comments on commit 79f0b49

Please sign in to comment.