Skip to content
This repository was archived by the owner on Nov 24, 2023. It is now read-only.

Commit ea66a07

Browse files
authored
.*: cherry-pick #2139 and update change log for v2.0.7 (#2161)
1 parent 11861f7 commit ea66a07

File tree

12 files changed

+169
-35
lines changed

12 files changed

+169
-35
lines changed

CHANGELOG.md

+17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
# DM Changelog
22

33
All notable changes to this project will be documented in this file.
4+
5+
## [2.0.7] 2021-09-23
6+
7+
### Bug fixes
8+
9+
- Fix the error that binlog event is purged when switching `enable-gtid` in source configuration from `false` to `true` [#2094](https://github.com/pingcap/dm/pull/2094)
10+
- Fix the memory leak problem of schema-tracker [#2133](https://github.com/pingcap/dm/pull/2133)
11+
12+
### Improvements
13+
14+
- Disable background statistic job in schema tracker to reduce CPU consumption [#2065](https://github.com/pingcap/dm/pull/2065)
15+
- Support regular expressions rules for online DDL shadow and trash tables [#2139](https://github.com/pingcap/dm/pull/2139)
16+
17+
### Known issues
18+
19+
[GitHub issues](https://github.com/pingcap/dm/issues?q=is%3Aissue+label%3Aaffected-v2.0.7)
20+
421
## [2.0.6] 2021-08-13
522

623
### Bug fixes

_utils/terror_gen/errors_release.txt

+1
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ ErrConfigGenBAList,[code=20044:class=config:scope=internal:level=high], "Message
176176
ErrConfigGenTableRouter,[code=20045:class=config:scope=internal:level=high], "Message: generate table router error, Workaround: Please check the `routes` config in task configuration file."
177177
ErrConfigGenColumnMapping,[code=20046:class=config:scope=internal:level=high], "Message: generate column mapping error, Workaround: Please check the `column-mappings` config in task configuration file."
178178
ErrConfigInvalidChunkFileSize,[code=20047:class=config:scope=internal:level=high], "Message: invalid `chunk-filesize` %v, Workaround: Please check the `chunk-filesize` config in task configuration file."
179+
ErrConfigOnlineDDLInvalidRegex,[code=20048:class=config:scope=internal:level=high], "Message: config '%s' regex pattern '%s' invalid, reason: %s, Workaround: Please check if params is correctly in the configuration file."
179180
ErrBinlogExtractPosition,[code=22001:class=binlog-op:scope=internal:level=high]
180181
ErrBinlogInvalidFilename,[code=22002:class=binlog-op:scope=internal:level=high], "Message: invalid binlog filename"
181182
ErrBinlogParsePosFromStr,[code=22003:class=binlog-op:scope=internal:level=high]

dm/config/subtask.go

+52
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"encoding/json"
1919
"flag"
2020
"fmt"
21+
"regexp"
2122
"strings"
2223

2324
"github.com/BurntSushi/toml"
@@ -38,6 +39,9 @@ const (
3839
ModeAll = "all"
3940
ModeFull = "full"
4041
ModeIncrement = "incremental"
42+
43+
DefaultShadowTableRules = "^_(.+)_(?:new|gho)$"
44+
DefaultTrashTableRules = "^_(.+)_(?:ghc|del|old)$"
4145
)
4246

4347
var defaultMaxIdleConns = 2
@@ -134,6 +138,11 @@ type SubTaskConfig struct {
134138
IsSharding bool `toml:"is-sharding" json:"is-sharding"`
135139
ShardMode string `toml:"shard-mode" json:"shard-mode"`
136140
OnlineDDL bool `toml:"online-ddl" json:"online-ddl"`
141+
142+
// pt/gh-ost name rule, support regex
143+
ShadowTableRules []string `yaml:"shadow-table-rules" toml:"shadow-table-rules" json:"shadow-table-rules"`
144+
TrashTableRules []string `yaml:"trash-table-rules" toml:"trash-table-rules" json:"trash-table-rules"`
145+
137146
// deprecated
138147
OnlineDDLScheme string `toml:"online-ddl-scheme" json:"online-ddl-scheme"`
139148

@@ -251,6 +260,29 @@ func (c *SubTaskConfig) Decode(data string, verifyDecryptPassword bool) error {
251260
return c.Adjust(verifyDecryptPassword)
252261
}
253262

263+
func adjustOnlineTableRules(ruleType string, rules []string) ([]string, error) {
264+
adjustedRules := make([]string, 0, len(rules))
265+
for _, r := range rules {
266+
if !strings.HasPrefix(r, "^") {
267+
r = "^" + r
268+
}
269+
270+
if !strings.HasSuffix(r, "$") {
271+
r += "$"
272+
}
273+
274+
p, err := regexp.Compile(r)
275+
if err != nil {
276+
return rules, terror.ErrConfigOnlineDDLInvalidRegex.Generate(ruleType, r, "fail to compile: "+err.Error())
277+
}
278+
if p.NumSubexp() != 1 {
279+
return rules, terror.ErrConfigOnlineDDLInvalidRegex.Generate(ruleType, r, "rule isn't contains exactly one submatch")
280+
}
281+
adjustedRules = append(adjustedRules, r)
282+
}
283+
return adjustedRules, nil
284+
}
285+
254286
// Adjust adjusts and verifies configs.
255287
func (c *SubTaskConfig) Adjust(verifyDecryptPassword bool) error {
256288
if c.Name == "" {
@@ -274,6 +306,26 @@ func (c *SubTaskConfig) Adjust(verifyDecryptPassword bool) error {
274306
return terror.ErrConfigOnlineSchemeNotSupport.Generate(c.OnlineDDLScheme)
275307
}
276308

309+
if len(c.ShadowTableRules) == 0 {
310+
c.ShadowTableRules = []string{DefaultShadowTableRules}
311+
} else {
312+
shadowTableRule, err := adjustOnlineTableRules("shadow-table-rules", c.ShadowTableRules)
313+
if err != nil {
314+
return err
315+
}
316+
c.ShadowTableRules = shadowTableRule
317+
}
318+
319+
if len(c.TrashTableRules) == 0 {
320+
c.TrashTableRules = []string{DefaultTrashTableRules}
321+
} else {
322+
trashTableRule, err := adjustOnlineTableRules("trash-table-rules", c.TrashTableRules)
323+
if err != nil {
324+
return err
325+
}
326+
c.TrashTableRules = trashTableRule
327+
}
328+
277329
if c.MetaSchema == "" {
278330
c.MetaSchema = defaultMetaSchema
279331
}

dm/config/task.go

+19-3
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ type TaskConfig struct {
300300
MySQLInstances []*MySQLInstance `yaml:"mysql-instances" toml:"mysql-instances" json:"mysql-instances"`
301301

302302
OnlineDDL bool `yaml:"online-ddl" toml:"online-ddl" json:"online-ddl"`
303+
// pt/gh-ost name rule,support regex
304+
ShadowTableRules []string `yaml:"shadow-table-rules" toml:"shadow-table-rules" json:"shadow-table-rules"`
305+
TrashTableRules []string `yaml:"trash-table-rules" toml:"trash-table-rules" json:"trash-table-rules"`
306+
303307
// deprecated
304308
OnlineDDLScheme string `yaml:"online-ddl-scheme" toml:"online-ddl-scheme" json:"online-ddl-scheme"`
305309

@@ -696,6 +700,8 @@ func (c *TaskConfig) SubTaskConfigs(sources map[string]DBConfig) ([]*SubTaskConf
696700
cfg.IsSharding = c.IsSharding
697701
cfg.ShardMode = c.ShardMode
698702
cfg.OnlineDDL = c.OnlineDDL
703+
cfg.TrashTableRules = c.TrashTableRules
704+
cfg.ShadowTableRules = c.ShadowTableRules
699705
cfg.IgnoreCheckingItems = c.IgnoreCheckingItems
700706
cfg.Name = c.Name
701707
cfg.Mode = c.TaskMode
@@ -1033,9 +1039,11 @@ type TaskConfigForDowngrade struct {
10331039
EnableANSIQuotes bool `yaml:"ansi-quotes"`
10341040
RemoveMeta bool `yaml:"remove-meta"`
10351041
// new config item
1036-
MySQLInstances []*MySQLInstanceForDowngrade `yaml:"mysql-instances"`
1037-
ExprFilter map[string]*ExpressionFilter `yaml:"expression-filter,omitempty"`
1038-
OnlineDDL bool `yaml:"online-ddl,omitempty"`
1042+
MySQLInstances []*MySQLInstanceForDowngrade `yaml:"mysql-instances"`
1043+
ExprFilter map[string]*ExpressionFilter `yaml:"expression-filter,omitempty"`
1044+
OnlineDDL bool `yaml:"online-ddl,omitempty"`
1045+
ShadowTableRules []string `yaml:"shadow-table-rules,omitempty"`
1046+
TrashTableRules []string `yaml:"trash-table-rules,omitempty"`
10391047
}
10401048

10411049
// NewTaskConfigForDowngrade create new TaskConfigForDowngrade.
@@ -1068,6 +1076,8 @@ func NewTaskConfigForDowngrade(taskConfig *TaskConfig) *TaskConfigForDowngrade {
10681076
MySQLInstances: NewMySQLInstancesForDowngrade(taskConfig.MySQLInstances),
10691077
ExprFilter: taskConfig.ExprFilter,
10701078
OnlineDDL: taskConfig.OnlineDDL,
1079+
ShadowTableRules: taskConfig.ShadowTableRules,
1080+
TrashTableRules: taskConfig.TrashTableRules,
10711081
}
10721082
}
10731083

@@ -1080,6 +1090,12 @@ func (c *TaskConfigForDowngrade) omitDefaultVals() {
10801090
delete(c.TargetDB.Session, "time_zone")
10811091
}
10821092
}
1093+
if len(c.ShadowTableRules) == 1 && c.ShadowTableRules[0] == DefaultShadowTableRules {
1094+
c.ShadowTableRules = nil
1095+
}
1096+
if len(c.TrashTableRules) == 1 && c.TrashTableRules[0] == DefaultTrashTableRules {
1097+
c.TrashTableRules = nil
1098+
}
10831099
}
10841100

10851101
// Yaml returns YAML format representation of config.

dm/config/task_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,8 @@ func (t *testConfig) TestGenAndFromSubTaskConfigs(c *C) {
648648
IsSharding: true,
649649
ShardMode: shardMode,
650650
OnlineDDL: onlineDDL,
651+
ShadowTableRules: []string{DefaultShadowTableRules},
652+
TrashTableRules: []string{DefaultTrashTableRules},
651653
CaseSensitive: true,
652654
Name: name,
653655
Mode: taskMode,

errors.toml

+6
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,12 @@ description = ""
10661066
workaround = "Please check the `chunk-filesize` config in task configuration file."
10671067
tags = ["internal", "high"]
10681068

1069+
[error.DM-config-20048]
1070+
message = "config '%s' regex pattern '%s' invalid, reason: %s"
1071+
description = ""
1072+
workaround = "Please check if params is correctly in the configuration file."
1073+
tags = ["internal", "high"]
1074+
10691075
[error.DM-binlog-op-22001]
10701076
message = ""
10711077
description = ""

pkg/terror/error_list.go

+3
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ const (
239239
codeConfigGenTableRouter
240240
codeConfigGenColumnMapping
241241
codeConfigInvalidChunkFileSize
242+
codeConfigOnlineDDLInvalidRegex
242243
)
243244

244245
// Binlog operation error code list.
@@ -862,6 +863,8 @@ var (
862863
ErrConfigGenTableRouter = New(codeConfigGenTableRouter, ClassConfig, ScopeInternal, LevelHigh, "generate table router error", "Please check the `routes` config in task configuration file.")
863864
ErrConfigGenColumnMapping = New(codeConfigGenColumnMapping, ClassConfig, ScopeInternal, LevelHigh, "generate column mapping error", "Please check the `column-mappings` config in task configuration file.")
864865
ErrConfigInvalidChunkFileSize = New(codeConfigInvalidChunkFileSize, ClassConfig, ScopeInternal, LevelHigh, "invalid `chunk-filesize` %v", "Please check the `chunk-filesize` config in task configuration file.")
866+
ErrConfigOnlineDDLInvalidRegex = New(codeConfigOnlineDDLInvalidRegex, ClassConfig, ScopeInternal, LevelHigh,
867+
"config '%s' regex pattern '%s' invalid, reason: %s", "Please check if params is correctly in the configuration file.")
865868

866869
// Binlog operation error.
867870
ErrBinlogExtractPosition = New(codeBinlogExtractPosition, ClassBinlogOp, ScopeInternal, LevelHigh, "", "")

syncer/online-ddl-tools/online_ddl.go

+40-9
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ package onlineddl
1616
import (
1717
"encoding/json"
1818
"fmt"
19-
"strings"
19+
"regexp"
2020
"sync"
2121

2222
"github.com/pingcap/failpoint"
@@ -379,13 +379,33 @@ func (s *Storage) CheckAndUpdate(
379379
// (_*).*_old ghost trash table
380380
// we don't support `--new-table-name` flag.
381381
type RealOnlinePlugin struct {
382-
storage *Storage
382+
storage *Storage
383+
shadowRegs []*regexp.Regexp
384+
trashRegs []*regexp.Regexp
383385
}
384386

385387
// NewRealOnlinePlugin returns real online plugin.
386388
func NewRealOnlinePlugin(tctx *tcontext.Context, cfg *config.SubTaskConfig) (OnlinePlugin, error) {
389+
shadowRegs := make([]*regexp.Regexp, 0, len(cfg.ShadowTableRules))
390+
trashRegs := make([]*regexp.Regexp, 0, len(cfg.TrashTableRules))
391+
for _, sg := range cfg.ShadowTableRules {
392+
shadowReg, err := regexp.Compile(sg)
393+
if err != nil {
394+
return nil, terror.ErrConfigOnlineDDLInvalidRegex.Generate("shadow-table-rules", sg, "fail to compile: "+err.Error())
395+
}
396+
shadowRegs = append(shadowRegs, shadowReg)
397+
}
398+
for _, tg := range cfg.TrashTableRules {
399+
trashReg, err := regexp.Compile(tg)
400+
if err != nil {
401+
return nil, terror.ErrConfigOnlineDDLInvalidRegex.Generate("trash-table-rules", tg, "fail to compile: "+err.Error())
402+
}
403+
trashRegs = append(trashRegs, trashReg)
404+
}
387405
r := &RealOnlinePlugin{
388-
storage: NewOnlineDDLStorage(tcontext.Background().WithLogger(tctx.L().WithFields(zap.String("online ddl", ""))), cfg), // create a context for logger
406+
storage: NewOnlineDDLStorage(tcontext.Background().WithLogger(tctx.L().WithFields(zap.String("online ddl", ""))), cfg), // create a context for logger
407+
shadowRegs: shadowRegs,
408+
trashRegs: trashRegs,
389409
}
390410

391411
return r, r.storage.Init(tctx)
@@ -487,12 +507,14 @@ func (r *RealOnlinePlugin) Finish(tctx *tcontext.Context, schema, table string)
487507
// TableType implements interface.
488508
func (r *RealOnlinePlugin) TableType(table string) TableType {
489509
// 5 is _ _gho/ghc/del or _ _old/new
490-
if len(table) > 5 && strings.HasPrefix(table, "_") {
491-
if strings.HasSuffix(table, "_gho") || strings.HasSuffix(table, "_new") {
510+
for _, shadowReg := range r.shadowRegs {
511+
if shadowReg.MatchString(table) {
492512
return GhostTable
493513
}
514+
}
494515

495-
if strings.HasSuffix(table, "_ghc") || strings.HasSuffix(table, "_del") || strings.HasSuffix(table, "_old") {
516+
for _, trashReg := range r.trashRegs {
517+
if trashReg.MatchString(table) {
496518
return TrashTable
497519
}
498520
}
@@ -501,9 +523,18 @@ func (r *RealOnlinePlugin) TableType(table string) TableType {
501523

502524
// RealName implements interface.
503525
func (r *RealOnlinePlugin) RealName(table string) string {
504-
tp := r.TableType(table)
505-
if tp == GhostTable || tp == TrashTable {
506-
table = table[1 : len(table)-4]
526+
for _, shadowReg := range r.shadowRegs {
527+
shadowRes := shadowReg.FindStringSubmatch(table)
528+
if len(shadowRes) > 1 {
529+
return shadowRes[1]
530+
}
531+
}
532+
533+
for _, trashReg := range r.trashRegs {
534+
trashRes := trashReg.FindStringSubmatch(table)
535+
if len(trashRes) > 1 {
536+
return trashRes[1]
537+
}
507538
}
508539
return table
509540
}

syncer/syncer_test.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,16 @@ func (s *testSyncerSuite) SetUpSuite(c *C) {
136136
Dir: loaderDir,
137137
}
138138
s.cfg = &config.SubTaskConfig{
139-
From: getDBConfigFromEnv(),
140-
To: getDBConfigFromEnv(),
141-
ServerID: 101,
142-
MetaSchema: "test",
143-
Name: "syncer_ut",
144-
Mode: config.ModeIncrement,
145-
Flavor: "mysql",
146-
LoaderConfig: loaderCfg,
139+
From: getDBConfigFromEnv(),
140+
To: getDBConfigFromEnv(),
141+
ServerID: 101,
142+
MetaSchema: "test",
143+
Name: "syncer_ut",
144+
ShadowTableRules: []string{config.DefaultShadowTableRules},
145+
TrashTableRules: []string{config.DefaultTrashTableRules},
146+
Mode: config.ModeIncrement,
147+
Flavor: "mysql",
148+
LoaderConfig: loaderCfg,
147149
}
148150
s.cfg.From.Adjust()
149151
s.cfg.To.Adjust()

tests/dmctl_basic/conf/get_task.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ mysql-instances:
6363
syncer: null
6464
syncer-thread: 0
6565
online-ddl: false
66+
shadow-table-rules: []
67+
trash-table-rules: []
6668
online-ddl-scheme: ""
6769
routes:
6870
route-01:

tests/import_goroutine_leak/run.sh

+15-15
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,21 @@ function run() {
7171
check_port_offline $WORKER1_PORT 20
7272
sleep 2
7373

74-
for ((k=0;k<10;k++)); do
75-
# dm-worker1 panics
76-
err_cnt=$(grep "panic" $WORK_DIR/worker1/log/stdout.log | wc -l)
77-
# there may be more panic
78-
if [ $err_cnt -lt 2 ]; then
79-
echo "dm-worker1 doesn't panic again, panic count ${err_cnt}"
80-
if [ $k -eq 9 ]; then
81-
echo "panic check failed 10 times, will exit now"
82-
exit 2
83-
fi
84-
else
85-
break
86-
fi
87-
sleep 2
88-
done
74+
for ((k = 0; k < 10; k++)); do
75+
# dm-worker1 panics
76+
err_cnt=$(grep "panic" $WORK_DIR/worker1/log/stdout.log | wc -l)
77+
# there may be more panic
78+
if [ $err_cnt -lt 2 ]; then
79+
echo "dm-worker1 doesn't panic again, panic count ${err_cnt}"
80+
if [ $k -eq 9 ]; then
81+
echo "panic check failed 10 times, will exit now"
82+
exit 2
83+
fi
84+
else
85+
break
86+
fi
87+
sleep 2
88+
done
8989

9090
echo "restart dm-workers with errros to pause"
9191
# paused with injected error

tests/import_v10x/conf/task.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ mysql-instances:
5757
syncer: null
5858
syncer-thread: 0
5959
online-ddl: false
60+
shadow-table-rules: []
61+
trash-table-rules: []
6062
online-ddl-scheme: ""
6163
routes: {}
6264
filters: {}

0 commit comments

Comments
 (0)