Skip to content

Commit

Permalink
config, sysvar: add config instance.enable_ddl and sysvar `tidb_ena…
Browse files Browse the repository at this point in the history
…ble_ddl` (pingcap#35425)

ref pingcap#34960
  • Loading branch information
CbcWestwolf authored and morgo committed Aug 1, 2022
1 parent f1f08b4 commit 607cde3
Show file tree
Hide file tree
Showing 18 changed files with 161 additions and 68 deletions.
1 change: 0 additions & 1 deletion br/cmd/br/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ go_library(
"//br/pkg/utils",
"//br/pkg/version/build",
"//config",
"//ddl",
"//parser/model",
"//session",
"//util",
Expand Down
4 changes: 2 additions & 2 deletions br/cmd/br/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/pingcap/tidb/br/pkg/trace"
"github.com/pingcap/tidb/br/pkg/utils"
"github.com/pingcap/tidb/br/pkg/version/build"
"github.com/pingcap/tidb/ddl"
"github.com/pingcap/tidb/config"
"github.com/pingcap/tidb/session"
"github.com/spf13/cobra"
"go.uber.org/zap"
Expand Down Expand Up @@ -78,7 +78,7 @@ func NewBackupCommand() *cobra.Command {
task.LogArguments(c)

// Do not run ddl worker in BR.
ddl.RunWorker = false
config.GetGlobalConfig().Instance.TiDBEnableDDL.Store(false)

summary.SetUnit(summary.BackupUnit)
return nil
Expand Down
2 changes: 1 addition & 1 deletion cmd/ddltest/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ go_test(
],
flaky = True,
deps = [
"//ddl",
"//config",
"//domain",
"//kv",
"//parser/model",
Expand Down
4 changes: 2 additions & 2 deletions cmd/ddltest/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
_ "github.com/go-sql-driver/mysql"
"github.com/pingcap/errors"
"github.com/pingcap/log"
"github.com/pingcap/tidb/ddl"
"github.com/pingcap/tidb/config"
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/parser/model"
Expand Down Expand Up @@ -116,7 +116,7 @@ func createDDLSuite(t *testing.T) (s *ddlSuite) {
// Stop current DDL worker, so that we can't be the owner now.
err = domain.GetDomain(s.ctx).DDL().Stop()
require.NoError(t, err)
ddl.RunWorker = false
config.GetGlobalConfig().Instance.TiDBEnableDDL.Store(false)
session.ResetStoreForWithTiKVTest(s.store)
s.dom.Close()
require.NoError(t, s.store.Close())
Expand Down
13 changes: 8 additions & 5 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ var (
"check-mb4-value-in-utf8": "tidb_check_mb4_value_in_utf8",
"enable-collect-execution-info": "tidb_enable_collect_execution_info",
"max-server-connections": "max_connections",
"run-ddl": "tidb_enable_ddl",
},
},
{
Expand Down Expand Up @@ -480,10 +481,11 @@ type Instance struct {
ForcePriority string `toml:"tidb_force_priority" json:"tidb_force_priority"`
MemoryUsageAlarmRatio float64 `toml:"tidb_memory_usage_alarm_ratio" json:"tidb_memory_usage_alarm_ratio"`
// EnableCollectExecutionInfo enables the TiDB to collect execution info.
EnableCollectExecutionInfo bool `toml:"tidb_enable_collect_execution_info" json:"tidb_enable_collect_execution_info"`
PluginDir string `toml:"plugin_dir" json:"plugin_dir"`
PluginLoad string `toml:"plugin_load" json:"plugin_load"`
MaxConnections uint32 `toml:"max_connections" json:"max_connections"`
EnableCollectExecutionInfo bool `toml:"tidb_enable_collect_execution_info" json:"tidb_enable_collect_execution_info"`
PluginDir string `toml:"plugin_dir" json:"plugin_dir"`
PluginLoad string `toml:"plugin_load" json:"plugin_load"`
MaxConnections uint32 `toml:"max_connections" json:"max_connections"`
TiDBEnableDDL AtomicBool `toml:"tidb_enable_ddl" json:"tidb_enable_ddl"`
}

func (l *Log) getDisableTimestamp() bool {
Expand Down Expand Up @@ -859,6 +861,7 @@ var defaultConf = Config{
PluginDir: "/data/deploy/plugin",
PluginLoad: "",
MaxConnections: 0,
TiDBEnableDDL: *NewAtomicBool(true),
},
Status: Status{
ReportStatus: true,
Expand Down Expand Up @@ -1194,7 +1197,7 @@ func (c *Config) Valid() error {
}
return fmt.Errorf("invalid store=%s, valid storages=%v", c.Store, nameList)
}
if c.Store == "mocktikv" && !c.RunDDL {
if c.Store == "mocktikv" && !c.Instance.TiDBEnableDDL.Load() {
return fmt.Errorf("can't disable DDL on mocktikv")
}
if c.MaxIndexLength < DefMaxIndexLength || c.MaxIndexLength > DefMaxOfMaxIndexLength {
Expand Down
6 changes: 3 additions & 3 deletions config/config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ path = "/tmp/tidb"
# The socket file to use for connection.
socket = "/tmp/tidb-{Port}.sock"

# Run ddl worker on this tidb-server.
run-ddl = true

# Schema lease duration, very dangerous to change only if you know what you do.
lease = "45s"

Expand Down Expand Up @@ -462,3 +459,6 @@ tidb_record_plan_in_slow_log = 1

# The maximum permitted number of simultaneous client connections. When the value is 0, the number of connections is unlimited.
max_connections = 0

# Run ddl worker on this tidb-server.
tidb_enable_ddl = true
20 changes: 13 additions & 7 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,6 @@ path = "/tmp/tidb"
# The socket file to use for connection.
socket = "/tmp/tidb-{Port}.sock"
# Run ddl worker on this tidb-server.
run-ddl = true
# Schema lease duration, very dangerous to change only if you know what you do.
lease = "45s"
Expand Down Expand Up @@ -310,6 +307,9 @@ enable-enum-length-limit = true
# The maximum permitted number of simultaneous client connections. When the value is 0, the number of connections is unlimited.
max_connections = 0
# Run ddl worker on this tidb-server.
tidb_enable_ddl = true
[log]
# Log level: debug, info, warn, error, fatal.
level = "info"
Expand Down Expand Up @@ -1022,7 +1022,10 @@ func TestConflictInstanceConfig(t *testing.T) {
// Just receive a warning and keep their respective values.
expectedConflictOptions := map[string]InstanceConfigSection{
"": {
"", map[string]string{"check-mb4-value-in-utf8": "tidb_check_mb4_value_in_utf8"},
"", map[string]string{
"check-mb4-value-in-utf8": "tidb_check_mb4_value_in_utf8",
"run-ddl": "tidb_enable_ddl",
},
},
"log": {
"log", map[string]string{"enable-slow-log": "tidb_enable_slow_log"},
Expand All @@ -1031,10 +1034,10 @@ func TestConflictInstanceConfig(t *testing.T) {
"performance", map[string]string{"force-priority": "tidb_force_priority"},
},
}
_, err = f.WriteString("check-mb4-value-in-utf8 = true \n" +
_, err = f.WriteString("check-mb4-value-in-utf8 = true \nrun-ddl = true \n" +
"[log] \nenable-slow-log = true \n" +
"[performance] \nforce-priority = \"NO_PRIORITY\"\n" +
"[instance] \ntidb_check_mb4_value_in_utf8 = false \ntidb_enable_slow_log = false \ntidb_force_priority = \"LOW_PRIORITY\"")
"[instance] \ntidb_check_mb4_value_in_utf8 = false \ntidb_enable_slow_log = false \ntidb_force_priority = \"LOW_PRIORITY\"\ntidb_enable_ddl = false")
require.NoError(t, err)
require.NoError(t, f.Sync())
err = conf.Load(configFile)
Expand All @@ -1046,6 +1049,8 @@ func TestConflictInstanceConfig(t *testing.T) {
require.Equal(t, false, conf.Instance.EnableSlowLog.Load())
require.Equal(t, "NO_PRIORITY", conf.Performance.ForcePriority)
require.Equal(t, "LOW_PRIORITY", conf.Instance.ForcePriority)
require.Equal(t, true, conf.RunDDL)
require.Equal(t, false, conf.Instance.TiDBEnableDDL.Load())
require.Equal(t, 0, len(DeprecatedOptions))
for _, conflictOption := range ConflictOptions {
expectedConflictOption, ok := expectedConflictOptions[conflictOption.SectionName]
Expand Down Expand Up @@ -1075,6 +1080,7 @@ func TestDeprecatedConfig(t *testing.T) {
"": {
"", map[string]string{
"enable-collect-execution-info": "tidb_enable_collect_execution_info",
"run-ddl": "tidb_enable_ddl",
},
},
"log": {
Expand All @@ -1090,7 +1096,7 @@ func TestDeprecatedConfig(t *testing.T) {
},
},
}
_, err = f.WriteString("enable-collect-execution-info = false \n" +
_, err = f.WriteString("enable-collect-execution-info = false \nrun-ddl = false \n" +
"[plugin] \ndir=\"/plugin-path\" \nload=\"audit-1,whitelist-1\" \n" +
"[log] \nslow-threshold = 100 \n" +
"[performance] \nmemory-usage-alarm-ratio = 0.5")
Expand Down
78 changes: 55 additions & 23 deletions ddl/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/pingcap/kvproto/pkg/kvrpcpb"
"github.com/pingcap/tidb/config"
"github.com/pingcap/tidb/ddl/util"
"github.com/pingcap/tidb/domain/infosync"
"github.com/pingcap/tidb/infoschema"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/meta"
Expand Down Expand Up @@ -565,6 +566,9 @@ func newDDL(ctx context.Context, options ...Option) *ddl {
ddlJobCh: make(chan struct{}, 100),
}

// Register functions for enable/disable ddl when changing system variable `tidb_enable_ddl`.
variable.EnableDDL = d.EnableDDL
variable.DisableDDL = d.DisableDDL
variable.SwitchConcurrentDDL = d.SwitchConcurrentDDL

return d
Expand Down Expand Up @@ -638,37 +642,36 @@ func (d *ddl) prepareWorkers4legacyDDL() {

// Start implements DDL.Start interface.
func (d *ddl) Start(ctxPool *pools.ResourcePool) error {
logutil.BgLogger().Info("[ddl] start DDL", zap.String("ID", d.uuid), zap.Bool("runWorker", RunWorker))
logutil.BgLogger().Info("[ddl] start DDL", zap.String("ID", d.uuid), zap.Bool("runWorker", config.GetGlobalConfig().Instance.TiDBEnableDDL.Load()))

d.wg.Run(d.limitDDLJobs)
d.sessPool = newSessionPool(ctxPool, d.store)
// If RunWorker is true, we need campaign owner and do DDL job.
// Otherwise, we needn't do that.
if RunWorker {
d.ownerManager.SetBeOwnerHook(func() {
var err error
d.ddlSeqNumMu.seqNum, err = d.GetNextDDLSeqNum()
if err != nil {
logutil.BgLogger().Error("error when getting the ddl history count", zap.Error(err))
}
})

err := d.ownerManager.CampaignOwner()
d.ownerManager.SetBeOwnerHook(func() {
var err error
d.ddlSeqNumMu.seqNum, err = d.GetNextDDLSeqNum()
if err != nil {
return errors.Trace(err)
logutil.BgLogger().Error("error when getting the ddl history count", zap.Error(err))
}
})

d.delRangeMgr = d.newDeleteRangeManager(ctxPool == nil)

d.delRangeMgr = d.newDeleteRangeManager(ctxPool == nil)
d.prepareWorkers4ConcurrencyDDL()
d.prepareWorkers4legacyDDL()

d.prepareWorkers4ConcurrencyDDL()
d.prepareWorkers4legacyDDL()
go d.schemaSyncer.StartCleanWork()
if config.TableLockEnabled() {
d.wg.Add(1)
go d.startCleanDeadTableLock()
}
metrics.DDLCounter.WithLabelValues(metrics.StartCleanWork).Inc()

go d.schemaSyncer.StartCleanWork()
if config.TableLockEnabled() {
d.wg.Add(1)
go d.startCleanDeadTableLock()
// If tidb_enable_ddl is true, we need campaign owner and do DDL job.
// Otherwise, we needn't do that.
if config.GetGlobalConfig().Instance.TiDBEnableDDL.Load() {
if err := d.EnableDDL(); err != nil {
return err
}
metrics.DDLCounter.WithLabelValues(metrics.StartCleanWork).Inc()
}

variable.RegisterStatistics(d)
Expand All @@ -681,6 +684,35 @@ func (d *ddl) Start(ctxPool *pools.ResourcePool) error {
return nil
}

// EnableDDL enable this node to execute ddl.
// Since ownerManager.CampaignOwner will start a new goroutine to run ownerManager.campaignLoop,
// we should make sure that before invoking EnableDDL(), ddl is DISABLE.
func (d *ddl) EnableDDL() error {
err := d.ownerManager.CampaignOwner()
return errors.Trace(err)
}

// DisableDDL disable this node to execute ddl.
// We should make sure that before invoking DisableDDL(), ddl is ENABLE.
func (d *ddl) DisableDDL() error {
if d.ownerManager.IsOwner() {
// If there is only one node, we should NOT disable ddl.
serverInfo, err := infosync.GetAllServerInfo(d.ctx)
if err != nil {
logutil.BgLogger().Error("[ddl] error when GetAllServerInfo", zap.Error(err))
return err
}
if len(serverInfo) <= 1 {
return dbterror.ErrDDLSetting.GenWithStackByArgs("can not disable ddl when there is only one instance")
}
// FIXME: if possible, when this node is the only node with DDL, ths setting of DisableDDL should fail.
}

// disable campaign by interrupting campaignLoop
d.ownerManager.CampaignCancel()
return nil
}

// GetNextDDLSeqNum return the next DDL seq num.
func (d *ddl) GetNextDDLSeqNum() (uint64, error) {
var count uint64
Expand Down Expand Up @@ -830,7 +862,7 @@ func getJobCheckInterval(job *model.Job, i int) (time.Duration, bool) {

func (d *ddl) asyncNotifyWorker(job *model.Job) {
// If the workers don't run, we needn't notify workers.
if !RunWorker {
if !config.GetGlobalConfig().Instance.TiDBEnableDDL.Load() {
return
}
if variable.EnableConcurrentDDL.Load() {
Expand Down
2 changes: 0 additions & 2 deletions ddl/ddl_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ import (
)

var (
// RunWorker indicates if this TiDB server starts DDL worker and can run DDL job.
RunWorker = true
// ddlWorkerID is used for generating the next DDL worker ID.
ddlWorkerID = atomicutil.NewInt32(0)
// WaitTimeWhenErrorOccurred is waiting interval when processing DDL jobs encounter errors.
Expand Down
2 changes: 2 additions & 0 deletions errno/errcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,8 @@ const (
ErrHTTPServiceError = 8243
ErrPartitionColumnStatsMissing = 8244
ErrColumnInChange = 8245
ErrDDLSetting = 8246

// TiKV/PD/TiFlash errors.
ErrPDServerTimeout = 9001
ErrTiKVServerTimeout = 9002
Expand Down
1 change: 1 addition & 0 deletions errno/errname.go
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,7 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{
ErrJSONObjectKeyTooLong: mysql.Message("TiDB does not yet support JSON objects with the key length >= 65536", nil),
ErrPartitionStatsMissing: mysql.Message("Build table: %s global-level stats failed due to missing partition-level stats", nil),
ErrPartitionColumnStatsMissing: mysql.Message("Build table: %s global-level stats failed due to missing partition-level column stats, please run analyze table to refresh columns of all partitions", nil),
ErrDDLSetting: mysql.Message("Error happened when enable/disable DDL: %s", nil),
ErrNotSupportedWithSem: mysql.Message("Feature '%s' is not supported when security enhanced mode is enabled", nil),

ErrPlacementPolicyCheck: mysql.Message("Placement policy didn't meet the constraint, reason: %s", nil),
Expand Down
5 changes: 5 additions & 0 deletions errors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,11 @@ error = '''
column %s id %d does not exist, this column may have been updated by other DDL ran in parallel
'''

["ddl:8246"]
error = '''
Error happened when enable/disable DDL: %s
'''

["domain:8027"]
error = '''
Information schema is out of date: schema failed to update in 1 lease, please make sure TiDB can connect to TiKV
Expand Down
Loading

0 comments on commit 607cde3

Please sign in to comment.