Skip to content

Commit

Permalink
executor: support global kill (pingcap#17649)
Browse files Browse the repository at this point in the history
  • Loading branch information
pingyu authored Oct 27, 2020
1 parent 56467c3 commit 272f964
Show file tree
Hide file tree
Showing 45 changed files with 2,619 additions and 144 deletions.
69 changes: 1 addition & 68 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,63 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

PROJECT=tidb
GOPATH ?= $(shell go env GOPATH)
P=8

# Ensure GOPATH is set before running build process.
ifeq "$(GOPATH)" ""
$(error Please set the environment variable GOPATH before running `make`)
endif
FAIL_ON_STDOUT := awk '{ print } END { if (NR > 0) { exit 1 } }'

CURDIR := $(shell pwd)
path_to_add := $(addsuffix /bin,$(subst :,/bin:,$(GOPATH))):$(PWD)/tools/bin
export PATH := $(path_to_add):$(PATH)

GO := GO111MODULE=on go
GOBUILD := $(GO) build $(BUILD_FLAG) -tags codes
GOBUILDCOVERAGE := GOPATH=$(GOPATH) cd tidb-server; $(GO) test -coverpkg="../..." -c .
GOTEST := $(GO) test -p $(P)
OVERALLS := GO111MODULE=on overalls
STATICCHECK := GO111MODULE=on staticcheck
TIDB_EDITION ?= Community

# Ensure TIDB_EDITION is set to Community or Enterprise before running build process.
ifneq "$(TIDB_EDITION)" "Community"
ifneq "$(TIDB_EDITION)" "Enterprise"
$(error Please set the correct environment variable TIDB_EDITION before running `make`)
endif
endif

ARCH := "`uname -s`"
LINUX := "Linux"
MAC := "Darwin"
PACKAGE_LIST := go list ./...| grep -vE "cmd"
PACKAGES ?= $$($(PACKAGE_LIST))
PACKAGE_DIRECTORIES := $(PACKAGE_LIST) | sed 's|github.com/pingcap/$(PROJECT)/||'
FILES := $$(find $$($(PACKAGE_DIRECTORIES)) -name "*.go")

FAILPOINT_ENABLE := $$(find $$PWD/ -type d | grep -vE "(\.git|tools)" | xargs tools/bin/failpoint-ctl enable)
FAILPOINT_DISABLE := $$(find $$PWD/ -type d | grep -vE "(\.git|tools)" | xargs tools/bin/failpoint-ctl disable)

LDFLAGS += -X "github.com/pingcap/parser/mysql.TiDBReleaseVersion=$(shell git describe --tags --dirty --always)"
LDFLAGS += -X "github.com/pingcap/tidb/util/versioninfo.TiDBBuildTS=$(shell date -u '+%Y-%m-%d %H:%M:%S')"
LDFLAGS += -X "github.com/pingcap/tidb/util/versioninfo.TiDBGitHash=$(shell git rev-parse HEAD)"
LDFLAGS += -X "github.com/pingcap/tidb/util/versioninfo.TiDBGitBranch=$(shell git rev-parse --abbrev-ref HEAD)"
LDFLAGS += -X "github.com/pingcap/tidb/util/versioninfo.TiDBEdition=$(TIDB_EDITION)"

TEST_LDFLAGS = -X "github.com/pingcap/tidb/config.checkBeforeDropLDFlag=1"
COVERAGE_SERVER_LDFLAGS = -X "github.com/pingcap/tidb/tidb-server.isCoverageServer=1"

CHECK_LDFLAGS += $(LDFLAGS) ${TEST_LDFLAGS}

TARGET = ""

# VB = Vector Benchmark
VB_FILE =
VB_FUNC =

include Makefile.common

.PHONY: all clean test gotest server dev benchkv benchraw check checklist parser tidy ddltest

Expand Down Expand Up @@ -207,17 +151,6 @@ tikv_integration_test: failpoint-enable
$(GOTEST) ./store/tikv/. -with-tikv=true || { $(FAILPOINT_DISABLE); exit 1; }
@$(FAILPOINT_DISABLE)

RACE_FLAG =
ifeq ("$(WITH_RACE)", "1")
RACE_FLAG = -race
GOBUILD = GOPATH=$(GOPATH) $(GO) build
endif

CHECK_FLAG =
ifeq ("$(WITH_CHECK)", "1")
CHECK_FLAG = $(TEST_LDFLAGS)
endif

server:
ifeq ($(TARGET), "")
CGO_ENABLED=1 $(GOBUILD) $(RACE_FLAG) -ldflags '$(LDFLAGS) $(CHECK_FLAG)' -o bin/tidb-server tidb-server/main.go
Expand Down
80 changes: 80 additions & 0 deletions Makefile.common
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Copyright 2020 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.

PROJECT=tidb
GOPATH ?= $(shell go env GOPATH)
P=8

# Ensure GOPATH is set before running build process.
ifeq "$(GOPATH)" ""
$(error Please set the environment variable GOPATH before running `make`)
endif
FAIL_ON_STDOUT := awk '{ print } END { if (NR > 0) { exit 1 } }'

CURDIR := $(shell pwd)
path_to_add := $(addsuffix /bin,$(subst :,/bin:,$(GOPATH))):$(PWD)/tools/bin
export PATH := $(path_to_add):$(PATH)

GO := GO111MODULE=on go
GOBUILD := $(GO) build $(BUILD_FLAG) -tags codes
GOBUILDCOVERAGE := GOPATH=$(GOPATH) cd tidb-server; $(GO) test -coverpkg="../..." -c .
GOTEST := $(GO) test -p $(P)
OVERALLS := GO111MODULE=on overalls
STATICCHECK := GO111MODULE=on staticcheck
TIDB_EDITION ?= Community

# Ensure TIDB_EDITION is set to Community or Enterprise before running build process.
ifneq "$(TIDB_EDITION)" "Community"
ifneq "$(TIDB_EDITION)" "Enterprise"
$(error Please set the correct environment variable TIDB_EDITION before running `make`)
endif
endif

ARCH := "`uname -s`"
LINUX := "Linux"
MAC := "Darwin"
PACKAGE_LIST := go list ./...| grep -vE "cmd|github.com\/pingcap\/tidb\/tests"
PACKAGES ?= $$($(PACKAGE_LIST))
PACKAGE_DIRECTORIES := $(PACKAGE_LIST) | sed 's|github.com/pingcap/$(PROJECT)/||'
FILES := $$(find $$($(PACKAGE_DIRECTORIES)) -name "*.go")

FAILPOINT_ENABLE := $$(find $$PWD/ -type d | grep -vE "(\.git|tools)" | xargs tools/bin/failpoint-ctl enable)
FAILPOINT_DISABLE := $$(find $$PWD/ -type d | grep -vE "(\.git|tools)" | xargs tools/bin/failpoint-ctl disable)

LDFLAGS += -X "github.com/pingcap/parser/mysql.TiDBReleaseVersion=$(shell git describe --tags --dirty --always)"
LDFLAGS += -X "github.com/pingcap/tidb/util/versioninfo.TiDBBuildTS=$(shell date -u '+%Y-%m-%d %H:%M:%S')"
LDFLAGS += -X "github.com/pingcap/tidb/util/versioninfo.TiDBGitHash=$(shell git rev-parse HEAD)"
LDFLAGS += -X "github.com/pingcap/tidb/util/versioninfo.TiDBGitBranch=$(shell git rev-parse --abbrev-ref HEAD)"
LDFLAGS += -X "github.com/pingcap/tidb/util/versioninfo.TiDBEdition=$(TIDB_EDITION)"

TEST_LDFLAGS = -X "github.com/pingcap/tidb/config.checkBeforeDropLDFlag=1"
COVERAGE_SERVER_LDFLAGS = -X "github.com/pingcap/tidb/tidb-server.isCoverageServer=1"

CHECK_LDFLAGS += $(LDFLAGS) ${TEST_LDFLAGS}

TARGET = ""

# VB = Vector Benchmark
VB_FILE =
VB_FUNC =

RACE_FLAG =
ifeq ("$(WITH_RACE)", "1")
RACE_FLAG = -race
GOBUILD = GOPATH=$(GOPATH) $(GO) build
endif

CHECK_FLAG =
ifeq ("$(WITH_CHECK)", "1")
CHECK_FLAG = $(TEST_LDFLAGS)
endif
1 change: 0 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ type Config struct {
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"`
PessimisticTxn PessimisticTxn `toml:"pessimistic-txn" json:"pessimistic-txn"`
CheckMb4ValueInUTF8 bool `toml:"check-mb4-value-in-utf8" json:"check-mb4-value-in-utf8"`
Expand Down
4 changes: 0 additions & 4 deletions config/config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,6 @@ enable-batch-dml = false
# Set system variable 'lower_case_table_names'
lower-case-table-names = 2

# Make "kill query" behavior compatible with MySQL. It's not recommend to
# turn on this option when TiDB server is behind a proxy.
compatible-kill-query = false

# check mb4 value in utf8 is used to control whether to check the mb4 characters when the charset is utf8.
check-mb4-value-in-utf8 = true

Expand Down
1 change: 0 additions & 1 deletion config/config_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ var (
"CheckMb4ValueInUTF8": {},
"EnableStreaming": {},
"TxnLocalLatches.Capacity": {},
"CompatibleKillQuery": {},
"TreatOldVersionUTF8AsUTF8MB4": {},
"OpenTracing.Enable": {},
"PreparedPlanCache.Enabled": {},
Expand Down
2 changes: 1 addition & 1 deletion ddl/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func TestT(t *testing.T) {
conf.AlterPrimaryKey = true
})

_, err := infosync.GlobalInfoSyncerInit(context.Background(), "t", nil, true)
_, err := infosync.GlobalInfoSyncerInit(context.Background(), "t", func() uint64 { return 1 }, nil, true)
if err != nil {
t.Fatal(err)
}
Expand Down
8 changes: 8 additions & 0 deletions distsql/request_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,14 @@ func (builder *RequestBuilder) SetConcurrency(concurrency int) *RequestBuilder {
return builder
}

// SetTiDBServerID sets "TiDBServerID" for "kv.Request"
// ServerID is a unique id of TiDB instance among the cluster.
// See https://github.com/pingcap/tidb/blob/master/docs/design/2020-06-01-global-kill.md
func (builder *RequestBuilder) SetTiDBServerID(serverID uint64) *RequestBuilder {
builder.Request.TiDBServerID = serverID
return builder
}

// TableRangesToKVRanges converts table ranges to "KeyRange".
func TableRangesToKVRanges(tid int64, ranges []*ranger.Range, fb *statistics.QueryFeedback) []kv.KeyRange {
return TablesRangesToKVRanges([]int64{tid}, ranges, fb)
Expand Down
73 changes: 73 additions & 0 deletions docs/design/2020-06-01-global-kill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Global Kill

- Author(s): [pingyu](https://github.com/pingyu) (Ping Yu)
- Last updated: 2020-10-25
- Discussion at: https://github.com/pingcap/tidb/issues/8854

## Abstract

This document introduces the design of global connection id, and the global `KILL <connId>` based on it.

## Background

Currently connection ids are local to TiDB instances, which means that a `KILL x` must be directed to the correct instance, and can not safely be load balanced across the cluster, as discussed [here](https://github.com/pingcap/tidb/issues/8854).

## Proposal

To support "Global Kill", we need:
1. Global connection ids, which are unique among all TiDB instances.
2. Redirect `KILL x` to target TiDB instance, on which the connection `x` is running.
3. Support both 32 & 64 bits `connId`, to be compatible with legacy 32 bits clients. In this stage, we only design the 64 bits `connId`, and left a `markup` to distinguish between these two kinds.

## Rationale

#### 1. Structure of `connId`
##### 64 bits version
```
63 62 41 40 1 0
+--+---------------------+--------------------------------------+------+
| | serverId | local connId |markup|
|=0| (22b) | (40b) | =1 |
+--+---------------------+--------------------------------------+------+
```
##### 32 bits version
(To be discussed in another RFC)
```
31 1 0
+-----------------------------+------+
| ??? |markup|
| ??? | =0 |
+-----------------------------+------+
```

#### 2. bit 63
Bit 63 is always __ZERO__, making `connId` in range of non-negative int64, to be more friendly to exists codes, and some languages don't have primitive type `uint64`.

#### 3. markup
- `markup == 0` indicates that the `connID` is just 32 bits long effectively, and high 32 bits should be all zeros. Compatible with legacy 32 bits clients.
- `markup == 1` indicates that the `connID` is 64 bits long. Incompatible with legacy 32 bits clients.
- `markup == 1` while __high 32 bits are zeros__, indicates that 32 bits truncation happens. See `Compatibility` section.


#### 4. serverId
`serverId` is selected RANDOMLY by each TiDB instance on startup, and the uniqueness is guaranteed by PD(etcd). `serverId` should be larger or equal to 1, to ensure that high 32 bits of `connId` is always non-zero, and make it possible to detect truncation.

On failure (e.g. fail connecting to PD, or all `serverId` are unavailable), we block any new connection.

`serverId` is kept by PD with a lease (defaults to 12 hours, long enough to avoid brutally killing any long-run SQL). If TiDB is disconnected to PD longer than half of the lease (defaults to 6 hours), all connections are killed, and no new connection is accepted, to avoid running with stale/incorrect `serverId`. On connection to PD restored, a new `serverId` is acquired before accepting new connection.

On single TiDB instance without PD, a `serverId` of `1` is assigned.

#### 5. local connId
`local connId` is allocated by each TiDB instance on establishing connections incrementally.

Integer overflow is ignored at this stage, as `local connId` should be long enough.

#### 6. global kill
On processing `KILL x` command, first extract `serverId` from `x`. Then if `serverId` aims to a remote TiDB instance, get the address from cluster info (see also [`CLUSTER_INFO`](https://docs.pingcap.com/tidb/stable/information-schema-cluster-info#cluster_info)), and redirect the command to it by "Coprocessor API" provided by the remote TiDB, along with the original user authentication.

## Compatibility

- Incompatible with legacy 32 bits clients. (According to some quick tests by now, MySQL client v8.0.19 supports `KILL` a connection with 64 bits `connId`, while `CTRL-C` does not, because it truncates the `connId` to 32 bits). A warning is set prompting that truncation happened, but user cannot see it, because `CTRL-C` is sent by a new connection in an instant.

- [`KILL TIDB`](https://docs.pingcap.com/tidb/v4.0/sql-statement-kill) syntax and [`compatible-kill-query`](https://docs.pingcap.com/tidb/v4.0/tidb-configuration-file#compatible-kill-query) configuration item are deprecated.
Loading

0 comments on commit 272f964

Please sign in to comment.