// Copyright 2017 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // See the License for the specific language governing permissions and // limitations under the License. package config import ( "crypto/tls" "crypto/x509" "io/ioutil" "time" "github.com/BurntSushi/toml" "github.com/pingcap/errors" "github.com/pingcap/tidb/util/logutil" tracing "github.com/uber/jaeger-client-go/config" ) // Config number limitations const ( MaxLogFileSize = 4096 // MB ) // Valid config maps var ( ValidStorage = map[string]bool{ "mocktikv": true, "tikv": true, } // checkTableBeforeDrop enable to execute `admin check table` before `drop table`. CheckTableBeforeDrop = false // checkBeforeDropLDFlag is a go build flag. checkBeforeDropLDFlag = "None" ) // Config contains configuration options. type Config struct { Host string `toml:"host" json:"host"` AdvertiseAddress string `toml:"advertise-address" json:"advertise-address"` Port uint `toml:"port" json:"port"` Cors string `toml:"cors" json:"cors"` Store string `toml:"store" json:"store"` Path string `toml:"path" json:"path"` Socket string `toml:"socket" json:"socket"` Lease string `toml:"lease" json:"lease"` RunDDL bool `toml:"run-ddl" json:"run-ddl"` SplitTable bool `toml:"split-table" json:"split-table"` TokenLimit uint `toml:"token-limit" json:"token-limit"` OOMAction string `toml:"oom-action" json:"oom-action"` MemQuotaQuery int64 `toml:"mem-quota-query" json:"mem-quota-query"` EnableStreaming bool `toml:"enable-streaming" json:"enable-streaming"` TxnLocalLatches TxnLocalLatches `toml:"txn-local-latches" json:"txn-local-latches"` // Set sys variable lower-case-table-names, ref: https://dev.mysql.com/doc/refman/5.7/en/identifier-case-sensitivity.html. // TODO: We actually only support mode 2, which keeps the original case, but the comparison is case-insensitive. LowerCaseTableNames int `toml:"lower-case-table-names" json:"lower-case-table-names"` Log Log `toml:"log" json:"log"` Security Security `toml:"security" json:"security"` Status Status `toml:"status" json:"status"` Performance Performance `toml:"performance" json:"performance"` PreparedPlanCache PreparedPlanCache `toml:"prepared-plan-cache" json:"prepared-plan-cache"` OpenTracing OpenTracing `toml:"opentracing" json:"opentracing"` ProxyProtocol ProxyProtocol `toml:"proxy-protocol" json:"proxy-protocol"` TiKVClient TiKVClient `toml:"tikv-client" json:"tikv-client"` Binlog Binlog `toml:"binlog" json:"binlog"` CompatibleKillQuery bool `toml:"compatible-kill-query" json:"compatible-kill-query"` Plugin Plugin `toml:"plugin" json:"plugin"` CheckMb4ValueInUtf8 bool `toml:"check-mb4-value-in-utf8" json:"check-mb4-value-in-utf8"` } // Log is the log section of config. type Log struct { // Log level. Level string `toml:"level" json:"level"` // Log format. one of json, text, or console. Format string `toml:"format" json:"format"` // Disable automatic timestamps in output. DisableTimestamp bool `toml:"disable-timestamp" json:"disable-timestamp"` // File log config. File logutil.FileLogConfig `toml:"file" json:"file"` SlowQueryFile string `toml:"slow-query-file" json:"slow-query-file"` SlowThreshold uint64 `toml:"slow-threshold" json:"slow-threshold"` ExpensiveThreshold uint `toml:"expensive-threshold" json:"expensive-threshold"` QueryLogMaxLen uint64 `toml:"query-log-max-len" json:"query-log-max-len"` } // Security is the security section of the config. type Security struct { SkipGrantTable bool `toml:"skip-grant-table" json:"skip-grant-table"` SSLCA string `toml:"ssl-ca" json:"ssl-ca"` SSLCert string `toml:"ssl-cert" json:"ssl-cert"` SSLKey string `toml:"ssl-key" json:"ssl-key"` ClusterSSLCA string `toml:"cluster-ssl-ca" json:"cluster-ssl-ca"` ClusterSSLCert string `toml:"cluster-ssl-cert" json:"cluster-ssl-cert"` ClusterSSLKey string `toml:"cluster-ssl-key" json:"cluster-ssl-key"` } // ToTLSConfig generates tls's config based on security section of the config. func (s *Security) ToTLSConfig() (*tls.Config, error) { var tlsConfig *tls.Config if len(s.ClusterSSLCA) != 0 { var certificates = make([]tls.Certificate, 0) if len(s.ClusterSSLCert) != 0 && len(s.ClusterSSLKey) != 0 { // Load the client certificates from disk certificate, err := tls.LoadX509KeyPair(s.ClusterSSLCert, s.ClusterSSLKey) if err != nil { return nil, errors.Errorf("could not load client key pair: %s", err) } certificates = append(certificates, certificate) } // Create a certificate pool from the certificate authority certPool := x509.NewCertPool() ca, err := ioutil.ReadFile(s.ClusterSSLCA) if err != nil { return nil, errors.Errorf("could not read ca certificate: %s", err) } // Append the certificates from the CA if !certPool.AppendCertsFromPEM(ca) { return nil, errors.New("failed to append ca certs") } tlsConfig = &tls.Config{ Certificates: certificates, RootCAs: certPool, } } return tlsConfig, nil } // Status is the status section of the config. type Status struct { ReportStatus bool `toml:"report-status" json:"report-status"` StatusPort uint `toml:"status-port" json:"status-port"` MetricsAddr string `toml:"metrics-addr" json:"metrics-addr"` MetricsInterval uint `toml:"metrics-interval" json:"metrics-interval"` RecordQPSbyDB bool `toml:"record-db-qps" json:"record-db-qps"` } // Performance is the performance section of the config. type Performance struct { MaxProcs uint `toml:"max-procs" json:"max-procs"` MaxMemory uint64 `toml:"max-memory" json:"max-memory"` TCPKeepAlive bool `toml:"tcp-keep-alive" json:"tcp-keep-alive"` CrossJoin bool `toml:"cross-join" json:"cross-join"` StatsLease string `toml:"stats-lease" json:"stats-lease"` RunAutoAnalyze bool `toml:"run-auto-analyze" json:"run-auto-analyze"` StmtCountLimit uint `toml:"stmt-count-limit" json:"stmt-count-limit"` FeedbackProbability float64 `toml:"feedback-probability" json:"feedback-probability"` QueryFeedbackLimit uint `toml:"query-feedback-limit" json:"query-feedback-limit"` PseudoEstimateRatio float64 `toml:"pseudo-estimate-ratio" json:"pseudo-estimate-ratio"` ForcePriority string `toml:"force-priority" json:"force-priority"` } // PlanCache is the PlanCache section of the config. type PlanCache struct { Enabled bool `toml:"enabled" json:"enabled"` Capacity uint `toml:"capacity" json:"capacity"` Shards uint `toml:"shards" json:"shards"` } // TxnLocalLatches is the TxnLocalLatches section of the config. type TxnLocalLatches struct { Enabled bool `toml:"enabled" json:"enabled"` Capacity uint `toml:"capacity" json:"capacity"` } // PreparedPlanCache is the PreparedPlanCache section of the config. type PreparedPlanCache struct { Enabled bool `toml:"enabled" json:"enabled"` Capacity uint `toml:"capacity" json:"capacity"` MemoryGuardRatio float64 `toml:"memory-guard-ratio" json:"memory-guard-ratio"` } // OpenTracing is the opentracing section of the config. type OpenTracing struct { Enable bool `toml:"enable" json:"enable"` Sampler OpenTracingSampler `toml:"sampler" json:"sampler"` Reporter OpenTracingReporter `toml:"reporter" json:"reporter"` RPCMetrics bool `toml:"rpc-metrics" json:"rpc-metrics"` } // OpenTracingSampler is the config for opentracing sampler. // See https://godoc.org/github.com/uber/jaeger-client-go/config#SamplerConfig type OpenTracingSampler struct { Type string `toml:"type" json:"type"` Param float64 `toml:"param" json:"param"` SamplingServerURL string `toml:"sampling-server-url" json:"sampling-server-url"` MaxOperations int `toml:"max-operations" json:"max-operations"` SamplingRefreshInterval time.Duration `toml:"sampling-refresh-interval" json:"sampling-refresh-interval"` } // OpenTracingReporter is the config for opentracing reporter. // See https://godoc.org/github.com/uber/jaeger-client-go/config#ReporterConfig type OpenTracingReporter struct { QueueSize int `toml:"queue-size" json:"queue-size"` BufferFlushInterval time.Duration `toml:"buffer-flush-interval" json:"buffer-flush-interval"` LogSpans bool `toml:"log-spans" json:"log-spans"` LocalAgentHostPort string `toml:"local-agent-host-port" json:"local-agent-host-port"` } // ProxyProtocol is the PROXY protocol section of the config. type ProxyProtocol struct { // PROXY protocol acceptable client networks. // Empty string means disable PROXY protocol, // * means all networks. Networks string `toml:"networks" json:"networks"` // PROXY protocol header read timeout, Unit is second. HeaderTimeout uint `toml:"header-timeout" json:"header-timeout"` } // TiKVClient is the config for tikv client. type TiKVClient struct { // GrpcConnectionCount is the max gRPC connections that will be established // with each tikv-server. GrpcConnectionCount uint `toml:"grpc-connection-count" json:"grpc-connection-count"` // After a duration of this time in seconds if the client doesn't see any activity it pings // the server to see if the transport is still alive. GrpcKeepAliveTime uint `toml:"grpc-keepalive-time" json:"grpc-keepalive-time"` // After having pinged for keepalive check, the client waits for a duration of Timeout in seconds // and if no activity is seen even after that the connection is closed. GrpcKeepAliveTimeout uint `toml:"grpc-keepalive-timeout" json:"grpc-keepalive-timeout"` // CommitTimeout is the max time which command 'commit' will wait. CommitTimeout string `toml:"commit-timeout" json:"commit-timeout"` // MaxTxnTimeUse is the max time a Txn may use (in seconds) from its startTS to commitTS. MaxTxnTimeUse uint `toml:"max-txn-time-use" json:"max-txn-time-use"` // MaxBatchSize is the max batch size when calling batch commands API. MaxBatchSize uint `toml:"max-batch-size" json:"max-batch-size"` // If TiKV load is greater than this, TiDB will wait for a while to avoid little batch. OverloadThreshold uint `toml:"overload-threshold" json:"overload-threshold"` // MaxBatchWaitTime in nanosecond is the max wait time for batch. MaxBatchWaitTime time.Duration `toml:"max-batch-wait-time" json:"max-batch-wait-time"` // BatchWaitSize is the max wait size for batch. BatchWaitSize uint `toml:"batch-wait-size" json:"batch-wait-size"` } // Binlog is the config for binlog. type Binlog struct { Enable string `toml:"enable" json:"enable"` WriteTimeout string `toml:"write-timeout" json:"write-timeout"` // If IgnoreError is true, when writing binlog meets error, TiDB would // ignore the error. IgnoreError bool `toml:"ignore-error" json:"ignore-error"` // Use socket file to write binlog, for compatible with kafka version tidb-binlog. BinlogSocket string `toml:"binlog-socket" json:"binlog-socket"` } // Plugin is the config for plugin type Plugin struct { Dir string `toml:"dir" json:"dir"` Load string `toml:"load" json:"load"` } var defaultConf = Config{ Host: "0.0.0.0", AdvertiseAddress: "", Port: 4000, Cors: "", Store: "mocktikv", Path: "/tmp/tidb", RunDDL: true, SplitTable: true, Lease: "45s", TokenLimit: 1000, OOMAction: "log", MemQuotaQuery: 32 << 30, EnableStreaming: false, CheckMb4ValueInUtf8: true, TxnLocalLatches: TxnLocalLatches{ Enabled: true, Capacity: 2048000, }, LowerCaseTableNames: 2, Log: Log{ Level: "info", Format: "text", File: logutil.NewFileLogConfig(true, logutil.DefaultLogMaxSize), SlowQueryFile: "tidb-slow.log", SlowThreshold: logutil.DefaultSlowThreshold, ExpensiveThreshold: 10000, QueryLogMaxLen: logutil.DefaultQueryLogMaxLen, }, Status: Status{ ReportStatus: true, StatusPort: 10080, MetricsInterval: 15, RecordQPSbyDB: false, }, Performance: Performance{ MaxMemory: 0, TCPKeepAlive: true, CrossJoin: true, StatsLease: "3s", RunAutoAnalyze: true, StmtCountLimit: 5000, FeedbackProbability: 0.05, QueryFeedbackLimit: 1024, PseudoEstimateRatio: 0.8, ForcePriority: "NO_PRIORITY", }, ProxyProtocol: ProxyProtocol{ Networks: "", HeaderTimeout: 5, }, PreparedPlanCache: PreparedPlanCache{ Enabled: false, Capacity: 100, MemoryGuardRatio: 0.1, }, OpenTracing: OpenTracing{ Enable: false, Sampler: OpenTracingSampler{ Type: "const", Param: 1.0, }, Reporter: OpenTracingReporter{}, }, TiKVClient: TiKVClient{ GrpcConnectionCount: 16, GrpcKeepAliveTime: 10, GrpcKeepAliveTimeout: 3, CommitTimeout: "41s", MaxTxnTimeUse: 590, MaxBatchSize: 128, OverloadThreshold: 200, MaxBatchWaitTime: 0, BatchWaitSize: 8, }, Binlog: Binlog{ Enable: "auto", WriteTimeout: "15s", }, } var globalConf = defaultConf // NewConfig creates a new config instance with default value. func NewConfig() *Config { conf := defaultConf return &conf } // 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 loads config options from a toml file. func (c *Config) Load(confFile string) error { _, err := toml.DecodeFile(confFile, c) if c.TokenLimit <= 0 { c.TokenLimit = 1000 } return errors.Trace(err) } // ToLogConfig converts *Log to *logutil.LogConfig. func (l *Log) ToLogConfig() *logutil.LogConfig { return logutil.NewLogConfig(l.Level, l.Format, l.SlowQueryFile, l.File, l.DisableTimestamp) } // ToTracingConfig converts *OpenTracing to *tracing.Configuration. func (t *OpenTracing) ToTracingConfig() *tracing.Configuration { ret := &tracing.Configuration{ Disabled: !t.Enable, RPCMetrics: t.RPCMetrics, Reporter: &tracing.ReporterConfig{}, Sampler: &tracing.SamplerConfig{}, } ret.Reporter.QueueSize = t.Reporter.QueueSize ret.Reporter.BufferFlushInterval = t.Reporter.BufferFlushInterval ret.Reporter.LogSpans = t.Reporter.LogSpans ret.Reporter.LocalAgentHostPort = t.Reporter.LocalAgentHostPort ret.Sampler.Type = t.Sampler.Type ret.Sampler.Param = t.Sampler.Param ret.Sampler.SamplingServerURL = t.Sampler.SamplingServerURL ret.Sampler.MaxOperations = t.Sampler.MaxOperations ret.Sampler.SamplingRefreshInterval = t.Sampler.SamplingRefreshInterval return ret } func init() { if checkBeforeDropLDFlag == "1" { CheckTableBeforeDrop = true } } // The following constants represents the valid action configurations for OOMAction. // NOTE: Although the values is case insensitive, we should use lower-case // strings because the configuration value will be transformed to lower-case // string and compared with these constants in the further usage. const ( OOMActionCancel = "cancel" OOMActionLog = "log" )