Skip to content

Commit b1a268b

Browse files
starter-bootstrap and branch
Signed-off-by: AmoebaProtozoa <8039876+AmoebaProtozoa@users.noreply.github.com>
1 parent 889d1a2 commit b1a268b

13 files changed

Lines changed: 680 additions & 3 deletions

File tree

cmd/tidb-server/BUILD.bazel

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
22

33
go_library(
44
name = "tidb-server_lib",
5-
srcs = ["main.go"],
5+
srcs = [
6+
"main.go",
7+
"starter.go",
8+
],
69
importpath = "github.com/pingcap/tidb/cmd/tidb-server",
710
visibility = ["//visibility:private"],
811
deps = [
@@ -70,8 +73,12 @@ go_library(
7073
"@com_github_pingcap_log//:log",
7174
"@com_github_prometheus_client_golang//prometheus",
7275
"@com_github_prometheus_client_golang//prometheus/push",
76+
"@com_github_tikv_client_go_v2//config",
7377
"@com_github_tikv_client_go_v2//tikv",
7478
"@com_github_tikv_client_go_v2//txnkv/transaction",
79+
"@com_github_tikv_pd_client//:client",
80+
"@com_github_tikv_pd_client//opt",
81+
"@com_github_tikv_pd_client//pkg/caller",
7582
"@org_uber_go_automaxprocs//maxprocs",
7683
"@org_uber_go_zap//:zap",
7784
],

cmd/tidb-server/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ func main() {
422422
setupMetrics()
423423

424424
keyspaceName := keyspace.GetKeyspaceNameBySettings()
425+
applyStarterKeyspaceMeta()
425426
executor.Start()
426427
resourcemanager.InstanceResourceManager.Start()
427428
storage, dom, err := createStoreDDLOwnerMgrAndDomain(keyspaceName)

cmd/tidb-server/starter.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright 2026 PingCAP, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
"context"
19+
"strconv"
20+
"time"
21+
22+
"github.com/pingcap/tidb/pkg/config"
23+
"github.com/pingcap/tidb/pkg/config/deploymode"
24+
"github.com/pingcap/tidb/pkg/keyspace"
25+
"github.com/pingcap/tidb/pkg/util/logutil"
26+
tikvconfig "github.com/tikv/client-go/v2/config"
27+
pd "github.com/tikv/pd/client"
28+
"github.com/tikv/pd/client/opt"
29+
"github.com/tikv/pd/client/pkg/caller"
30+
"go.uber.org/zap"
31+
)
32+
33+
// applyStarterKeyspaceMeta copies starter branch/restore labels from PD's
34+
// keyspace meta into the global config. No-op outside starter mode.
35+
func applyStarterKeyspaceMeta() {
36+
if !deploymode.IsStarter() {
37+
return
38+
}
39+
cfg := config.GetGlobalConfig()
40+
if keyspace.IsKeyspaceNameEmpty(cfg.KeyspaceName) || cfg.Store != config.StoreTypeTiKV {
41+
return
42+
}
43+
pdAddrs, _, _, err := tikvconfig.ParsePath("tikv://" + cfg.Path)
44+
if err != nil {
45+
logutil.BgLogger().Fatal("starter: parse pd path failed", zap.Error(err))
46+
}
47+
48+
timeout := time.Duration(cfg.PDClient.PDServerTimeout) * time.Second
49+
pdCli, err := pd.NewClient(caller.Component("tidb-starter-meta"), pdAddrs, pd.SecurityOption{
50+
CAPath: cfg.Security.ClusterSSLCA,
51+
CertPath: cfg.Security.ClusterSSLCert,
52+
KeyPath: cfg.Security.ClusterSSLKey,
53+
}, opt.WithCustomTimeoutOption(timeout))
54+
if err != nil {
55+
logutil.BgLogger().Fatal("starter: pd client init failed", zap.Error(err))
56+
}
57+
defer pdCli.Close()
58+
59+
ctx, cancel := context.WithTimeout(context.Background(), timeout)
60+
defer cancel()
61+
meta, err := pdCli.LoadKeyspace(ctx, cfg.KeyspaceName)
62+
if err != nil {
63+
logutil.BgLogger().Fatal("starter: load keyspace meta failed",
64+
zap.String("keyspace", cfg.KeyspaceName), zap.Error(err))
65+
}
66+
if meta == nil || meta.Config == nil {
67+
return
68+
}
69+
config.UpdateGlobal(func(c *config.Config) {
70+
if v, ok := meta.Config[keyspace.LabelIsBranch]; ok {
71+
c.Starter.IsBranch, _ = strconv.ParseBool(v)
72+
}
73+
if v, ok := meta.Config[keyspace.LabelIsBranchBootstrapped]; ok {
74+
c.Starter.IsBranchBootstrapped = v
75+
}
76+
if v, ok := meta.Config[keyspace.LabelIsBootstrappedForRestore]; ok {
77+
c.Starter.IsBootstrappedForRestore = v
78+
}
79+
})
80+
}

pkg/config/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ go_library(
66
"config.go",
77
"config_util.go",
88
"const.go",
9+
"starter.go",
910
"store.go",
1011
"tiflash.go",
1112
],

pkg/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ type Config struct {
232232
DXFResourceLimit int `toml:"dxf-resource-limit" json:"dxf-resource-limit"`
233233
KeyspaceName string `toml:"keyspace-name" json:"keyspace-name"`
234234
TiKVWorkerURL string `toml:"tikv-worker-url" json:"tikv-worker-url"`
235+
Starter Starter `toml:"starter" json:"starter"`
235236
Log Log `toml:"log" json:"log"`
236237
Instance Instance `toml:"instance" json:"instance"`
237238
Security Security `toml:"security" json:"security"`

pkg/config/starter.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2026 PingCAP, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package config
16+
17+
// Starter holds runtime state for starter deployment mode, populated from
18+
// keyspace meta during startup. Fields are only consulted when
19+
// deploymode.IsStarter() is true.
20+
type Starter struct {
21+
// IsBranch is true when this cluster is a branch of another cluster.
22+
IsBranch bool `toml:"is-branch" json:"is-branch"`
23+
// IsBranchBootstrapped: "True" once branch users have been amended,
24+
// empty when unknown (fall back to local mysql.tidb marker).
25+
IsBranchBootstrapped string `toml:"is-branch-bootstrapped" json:"is-branch-bootstrapped"`
26+
// IsBootstrappedForRestore: "True" once a restored cluster has been
27+
// amended; empty when not from restore.
28+
IsBootstrappedForRestore string `toml:"is-bootstrapped-for-restore" json:"is-bootstrapped-for-restore"`
29+
}

pkg/keyspace/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go_library(
55
srcs = [
66
"doc.go",
77
"keyspace.go",
8+
"starter_labels.go",
89
],
910
importpath = "github.com/pingcap/tidb/pkg/keyspace",
1011
visibility = ["//visibility:public"],

pkg/keyspace/starter_labels.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2026 PingCAP, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package keyspace
16+
17+
// Keys read from keyspacepb.KeyspaceMeta.Config in starter deployment mode.
18+
const (
19+
// LabelIsBranch marks a keyspace as a branch of another cluster.
20+
LabelIsBranch = "starter_is_branch"
21+
// LabelIsBranchBootstrapped tracks whether the branch's user/privilege
22+
// tables have been amended after creation.
23+
LabelIsBranchBootstrapped = "starter_is_branch_bootstrapped"
24+
// LabelIsBootstrappedForRestore tracks whether a restored cluster's
25+
// user/privilege tables have been amended.
26+
LabelIsBootstrappedForRestore = "starter_is_bootstrapped_for_restore"
27+
)

pkg/session/BUILD.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ go_library(
99
"mock_bootstrap.go",
1010
"nontransactional.go",
1111
"session.go",
12+
"starter_bootstrap.go",
1213
"sync_upgrade.go",
1314
"testutil.go", #keep
1415
"tidb.go",
@@ -22,6 +23,7 @@ go_library(
2223
deps = [
2324
"//pkg/bindinfo",
2425
"//pkg/config",
26+
"//pkg/config/deploymode",
2527
"//pkg/config/kerneltype",
2628
"//pkg/ddl",
2729
"//pkg/ddl/placement",
@@ -159,6 +161,7 @@ go_test(
159161
"bootstrap_test.go",
160162
"main_test.go",
161163
"session_test.go",
164+
"starter_bootstrap_test.go",
162165
"tidb_test.go",
163166
"upgrade_backfill_test.go",
164167
"upgrade_test.go",
@@ -171,6 +174,7 @@ go_test(
171174
"//pkg/autoid_service",
172175
"//pkg/bindinfo",
173176
"//pkg/config",
177+
"//pkg/config/deploymode",
174178
"//pkg/config/kerneltype",
175179
"//pkg/ddl",
176180
"//pkg/domain",

pkg/session/bootstrap.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030

3131
"github.com/pingcap/errors"
3232
"github.com/pingcap/tidb/pkg/config"
33+
"github.com/pingcap/tidb/pkg/config/deploymode"
3334
"github.com/pingcap/tidb/pkg/config/kerneltype"
3435
"github.com/pingcap/tidb/pkg/domain"
3536
"github.com/pingcap/tidb/pkg/infoschema"
@@ -472,6 +473,7 @@ func doBootstrapSQLFile(s sessionapi.Session) error {
472473
// All the statements run in a single transaction.
473474
func doDMLWorks(s sessionapi.Session) {
474475
mustExecute(s, "BEGIN")
476+
rootName := starterRootUserName()
475477
if config.GetGlobalConfig().Security.SecureBootstrap {
476478
// If secure bootstrap is enabled, we create a root@localhost account which can login with auth_socket.
477479
// i.e. mysql -S /tmp/tidb.sock -uroot
@@ -483,12 +485,12 @@ func doDMLWorks(s sessionapi.Session) {
483485
mustExecute(s, `INSERT HIGH_PRIORITY INTO mysql.user (Host,User,authentication_string,plugin,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Process_priv,Grant_priv,References_priv,Alter_priv,Show_db_priv,
484486
Super_priv,Create_tmp_table_priv,Lock_tables_priv,Execute_priv,Create_view_priv,Show_view_priv,Create_routine_priv,Alter_routine_priv,Index_priv,Create_user_priv,Event_priv,Repl_slave_priv,Repl_client_priv,Trigger_priv,Create_role_priv,Drop_role_priv,Account_locked,
485487
Shutdown_priv,Reload_priv,FILE_priv,Config_priv,Create_Tablespace_Priv,User_attributes,Token_issuer) VALUES
486-
("localhost", "root", %?, "auth_socket", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "N", "Y", "Y", "Y", "Y", "Y", null, "")`, u.Username)
488+
("localhost", %?, %?, "auth_socket", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "N", "Y", "Y", "Y", "Y", "Y", null, "")`, rootName, u.Username)
487489
} else {
488490
mustExecute(s, `INSERT HIGH_PRIORITY INTO mysql.user (Host,User,authentication_string,plugin,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Process_priv,Grant_priv,References_priv,Alter_priv,Show_db_priv,
489491
Super_priv,Create_tmp_table_priv,Lock_tables_priv,Execute_priv,Create_view_priv,Show_view_priv,Create_routine_priv,Alter_routine_priv,Index_priv,Create_user_priv,Event_priv,Repl_slave_priv,Repl_client_priv,Trigger_priv,Create_role_priv,Drop_role_priv,Account_locked,
490492
Shutdown_priv,Reload_priv,FILE_priv,Config_priv,Create_Tablespace_Priv,User_attributes,Token_issuer) VALUES
491-
("%", "root", "", "mysql_native_password", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "N", "Y", "Y", "Y", "Y", "Y", null, "")`)
493+
("%", %?, "", "mysql_native_password", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "N", "Y", "Y", "Y", "Y", "Y", null, "")`, rootName)
492494
}
493495

494496
// For GLOBAL scoped system variables, insert the initial value
@@ -528,6 +530,10 @@ func doDMLWorks(s sessionapi.Session) {
528530

529531
writeClusterID(s)
530532

533+
if deploymode.IsStarter() {
534+
doStarterBootstrap(s)
535+
}
536+
531537
ctx := kv.WithInternalSourceType(context.Background(), kv.InternalTxnBootstrap)
532538
_, err := s.ExecuteInternal(ctx, "COMMIT")
533539
if err != nil {

0 commit comments

Comments
 (0)