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

config: support to dynamically update some config items read from PD #14750

Merged
merged 26 commits into from
Feb 17, 2020
Merged
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
137 changes: 57 additions & 80 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,23 @@
package config

import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io/ioutil"
"net/url"
"os"
"reflect"
"strings"
"sync"
"time"

"github.com/BurntSushi/toml"
"github.com/pingcap/errors"
zaplog "github.com/pingcap/log"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/parser/terror"
"github.com/pingcap/tidb/util/logutil"
tracing "github.com/uber/jaeger-client-go/config"
"go.uber.org/atomic"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -114,6 +111,9 @@ type Config struct {
NewCollationsEnabledOnFirstBootstrap bool `toml:"new_collations_enabled_on_first_bootstrap" json:"new_collations_enabled_on_first_bootstrap"`
// Experimental contains parameters for experimental features.
Experimental Experimental `toml:"experimental" json:"experimental"`
// EnableDynamicConfig enables the TiDB to fetch configs from PD and update itself during runtime.
// see https://github.com/pingcap/tidb/pull/13660 for more details.
EnableDynamicConfig bool `toml:"enable-dynamic-config" json:"enable-dynamic-config"`
}

// nullableBool defaults unset bool options to unset instead of false, which enables us to know if the user has set 2
Expand Down Expand Up @@ -613,15 +613,11 @@ var defaultConf = Config{
Experimental: Experimental{
AllowAutoRandom: false,
},
EnableDynamicConfig: false,
}

var (
globalConf = atomic.Value{}
reloadConfPath = ""
confReloader func(nc, c *Config)
confReloadLock sync.Mutex
supportedReloadConfigs = make(map[string]struct{}, 32)
supportedReloadConfList = make([]string, 0, 32)
globalConfHandler ConfHandler
)

// NewConfig creates a new config instance with default value.
Expand All @@ -630,94 +626,72 @@ func NewConfig() *Config {
return &conf
}

// SetConfReloader sets reload config path and a reloader.
// It should be called only once at start time.
func SetConfReloader(cpath string, reloader func(nc, c *Config), confItems ...string) {
reloadConfPath = cpath
confReloader = reloader
for _, item := range confItems {
supportedReloadConfigs[item] = struct{}{}
supportedReloadConfList = append(supportedReloadConfList, item)
}
}

// GetGlobalConfig returns the global configuration for this server.
// It should store configuration from command line and configuration file.
// Other parts of the system can read the global configuration use this function.
func GetGlobalConfig() *Config {
return globalConf.Load().(*Config)
return globalConfHandler.GetConfig()
}

// StoreGlobalConfig stores a new config to the globalConf. It mostly uses in the test to avoid some data races.
func StoreGlobalConfig(config *Config) {
globalConf.Store(config)
if err := globalConfHandler.SetConfig(config); err != nil {
logutil.BgLogger().Error("update the global config error", zap.Error(err))
}
}

// ReloadGlobalConfig reloads global configuration for this server.
func ReloadGlobalConfig() error {
confReloadLock.Lock()
defer confReloadLock.Unlock()

nc := NewConfig()
if err := nc.Load(reloadConfPath); err != nil {
return err
}
if err := nc.Valid(); err != nil {
return err
}
c := GetGlobalConfig()
var deprecatedConfig = map[string]struct{}{
"pessimistic-txn.ttl": {},
"log.rotate": {},
}

diffs := collectsDiff(*nc, *c, "")
if len(diffs) == 0 {
return nil
}
var formattedDiff bytes.Buffer
for k, vs := range diffs {
formattedDiff.WriteString(fmt.Sprintf(", %v:%v->%v", k, vs[1], vs[0]))
}
unsupported := make([]string, 0, 2)
for k := range diffs {
if _, ok := supportedReloadConfigs[k]; !ok {
unsupported = append(unsupported, k)
func isAllDeprecatedConfigItems(items []string) bool {
for _, item := range items {
if _, ok := deprecatedConfig[item]; !ok {
return false
}
}
if len(unsupported) > 0 {
return fmt.Errorf("reloading config %v is not supported, only %v are supported now, "+
"your changes%s", unsupported, supportedReloadConfList, formattedDiff.String())
}

confReloader(nc, c)
globalConf.Store(nc)
logutil.BgLogger().Info("reload config changes" + formattedDiff.String())
return nil
return true
}

// collectsDiff collects different config items.
// map[string][]string -> map[field path][]{new value, old value}
func collectsDiff(i1, i2 interface{}, fieldPath string) map[string][]interface{} {
diff := make(map[string][]interface{})
t := reflect.TypeOf(i1)
if t.Kind() != reflect.Struct {
if reflect.DeepEqual(i1, i2) {
return diff
// InitializeConfig initialize the global config handler.
// The function enforceCmdArgs is used to merge the config file with command arguments:
// For example, if you start TiDB by the command "./tidb-server --port=3000", the port number should be
// overwritten to 3000 and ignore the port number in the config file.
func InitializeConfig(confPath string, configCheck, configStrict bool, reloadFunc ConfReloadFunc, enforceCmdArgs func(*Config)) {
cfg := GetGlobalConfig()
var err error
if confPath != "" {
if err = cfg.Load(confPath); err != nil {
// Unused config item error turns to warnings.
if tmp, ok := err.(*ErrConfigValidationFailed); ok {
if isAllDeprecatedConfigItems(tmp.UndecodedItems) {
fmt.Fprintln(os.Stderr, err.Error())
err = nil
}
// This block is to accommodate an interim situation where strict config checking
// is not the default behavior of TiDB. The warning message must be deferred until
// logging has been set up. After strict config checking is the default behavior,
// This should all be removed.
if !configCheck && !configStrict {
fmt.Fprintln(os.Stderr, err.Error())
err = nil
}
}
}
diff[fieldPath] = []interface{}{i1, i2}
return diff
}

v1 := reflect.ValueOf(i1)
v2 := reflect.ValueOf(i2)
for i := 0; i < v1.NumField(); i++ {
p := t.Field(i).Name
if fieldPath != "" {
p = fieldPath + "." + p
}
m := collectsDiff(v1.Field(i).Interface(), v2.Field(i).Interface(), p)
for k, v := range m {
diff[k] = v
terror.MustNil(err)
} else {
// configCheck should have the config file specified.
if configCheck {
fmt.Fprintln(os.Stderr, "config check failed", errors.New("no config file specified for config-check"))
os.Exit(1)
}
}
return diff
enforceCmdArgs(cfg)
globalConfHandler, err = NewConfHandler(cfg, reloadFunc, nil)
terror.MustNil(err)
globalConfHandler.Start()
}

// Load loads config options from a toml file.
Expand Down Expand Up @@ -864,7 +838,10 @@ func (t *OpenTracing) ToTracingConfig() *tracing.Configuration {
}

func init() {
globalConf.Store(&defaultConf)
conf := defaultConf
cch := new(constantConfHandler)
cch.curConf.Store(&conf)
globalConfHandler = cch
if checkBeforeDropLDFlag == "1" {
CheckTableBeforeDrop = true
}
Expand Down
4 changes: 4 additions & 0 deletions config/config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ delay-clean-table-lock = 0
# Maximum number of the splitting region, which is used by the split region statement.
split-region-max-num = 1000

# enable the TiDB to fetch configs from PD and update itself during runtime.
# see https://github.com/pingcap/tidb/pull/13660 for more details.
enable-dynamic-config = false

# alter-primary-key is used to control alter primary key feature. Default is false, indicate the alter primary key feature is disabled.
# If it is true, we can add the primary key by "alter table", but we may not be able to drop the primary key.
# In order to support "drop primary key" operation , this flag must be true and the table does not have the pkIsHandle flag.
Expand Down
Loading