diff --git a/br/pkg/glue/glue.go b/br/pkg/glue/glue.go index 4c203179146f57ef35f1d91d8cd9954f15ba21a4..24b0852d312903d8af2d6c2bbee1223f9c69c7c6 100644 --- a/br/pkg/glue/glue.go +++ b/br/pkg/glue/glue.go @@ -38,6 +38,7 @@ type Session interface { CreateTable(ctx context.Context, dbName model.CIStr, table *model.TableInfo) error CreatePlacementPolicy(ctx context.Context, policy *model.PolicyInfo) error Close() + GetGlobalVariable(name string) (string, error) } // BatchCreateTableSession is an interface to batch create table parallelly diff --git a/br/pkg/gluetidb/glue.go b/br/pkg/gluetidb/glue.go index 1b514596b2ff0417055b1f9f03546c6e8952c81b..d17a098613648554c59040aa6b2f6e5f5fc7505d 100644 --- a/br/pkg/gluetidb/glue.go +++ b/br/pkg/gluetidb/glue.go @@ -203,6 +203,11 @@ func (gs *tidbSession) Close() { gs.se.Close() } +// GetGlobalVariables implements glue.Session. +func (gs *tidbSession) GetGlobalVariable(name string) (string, error) { + return gs.se.GetSessionVars().GlobalVarsAccessor.GetTiDBTableValue(name) +} + // showCreateTable shows the result of SHOW CREATE TABLE from a TableInfo. func (gs *tidbSession) showCreateTable(tbl *model.TableInfo) (string, error) { table := tbl.Clone() diff --git a/br/pkg/task/backup.go b/br/pkg/task/backup.go index bcd8eb06ce042c87b2c553482b68f84b70106163..a94d943577c440627d65bf1dc6f01f3712807972 100644 --- a/br/pkg/task/backup.go +++ b/br/pkg/task/backup.go @@ -261,6 +261,16 @@ func RunBackup(c context.Context, g glue.Glue, cmdName string, cfg *BackupConfig statsHandle = mgr.GetDomain().StatsHandle() } + se, err := g.CreateSession(mgr.GetStorage()) + if err != nil { + return errors.Trace(err) + } + newCollationEnable, err := se.GetGlobalVariable(tidbNewCollationEnabled) + if err != nil { + return errors.Trace(err) + } + log.Info("get newCollationEnable for check during restore", zap.String("newCollationEnable", newCollationEnable)) + client, err := backup.NewBackupClient(ctx, mgr) if err != nil { return errors.Trace(err) @@ -351,6 +361,7 @@ func RunBackup(c context.Context, g glue.Glue, cmdName string, cfg *BackupConfig m.ClusterId = req.ClusterId m.ClusterVersion = clusterVersion m.BrVersion = brVersion + m.NewCollationsEnabled = newCollationEnable }) log.Info("get placement policies", zap.Int("count", len(policies))) diff --git a/br/pkg/task/common.go b/br/pkg/task/common.go index 3a8fdf7994cd692493d0ed1c454e139dae8d8c47..969c4fbf00dceec5b6e0cd1b1a823e2f9cb4b0f7 100644 --- a/br/pkg/task/common.go +++ b/br/pkg/task/common.go @@ -85,6 +85,8 @@ const ( crypterAES128KeyLen = 16 crypterAES192KeyLen = 24 crypterAES256KeyLen = 32 + + tidbNewCollationEnabled = "new_collation_enabled" ) // TLSConfig is the common configuration for TLS connection. diff --git a/br/pkg/task/restore.go b/br/pkg/task/restore.go index 89bb71e49ae84554e18d16aeb8ebec38fb14e009..f88440dca644714a0ee2eb53fc8522141f0bd7e2 100644 --- a/br/pkg/task/restore.go +++ b/br/pkg/task/restore.go @@ -4,6 +4,7 @@ package task import ( "context" + "strings" "time" "github.com/opentracing/opentracing-go" @@ -21,6 +22,7 @@ import ( "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/br/pkg/version" "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/kv" "github.com/spf13/pflag" "go.uber.org/multierr" "go.uber.org/zap" @@ -265,6 +267,42 @@ func CheckRestoreDBAndTable(client *restore.Client, cfg *RestoreConfig) error { return nil } +func CheckNewCollationEnable( + backupNewCollationEnable string, + g glue.Glue, + storage kv.Storage, + CheckRequirements bool, +) error { + if backupNewCollationEnable == "" { + if CheckRequirements { + return errors.Annotatef(berrors.ErrUnknown, + "NewCollactionEnable not found in backupmeta. "+ + "if you ensure the NewCollactionEnable config of backup cluster is as same as restore cluster, "+ + "use --check-requirements=false to skip") + } else { + log.Warn("no NewCollactionEnable in backup") + return nil + } + } + + se, err := g.CreateSession(storage) + if err != nil { + return errors.Trace(err) + } + + newCollationEnable, err := se.GetGlobalVariable(tidbNewCollationEnabled) + if err != nil { + return errors.Trace(err) + } + + if !strings.EqualFold(backupNewCollationEnable, newCollationEnable) { + return errors.Annotatef(berrors.ErrUnknown, + "newCollationEnable not match, upstream:%v, downstream: %v", + backupNewCollationEnable, newCollationEnable) + } + return nil +} + func isFullRestore(cmdName string) bool { return cmdName == FullRestoreCmd } @@ -315,6 +353,10 @@ func RunRestore(c context.Context, g glue.Glue, cmdName string, cfg *RestoreConf return errors.Trace(versionErr) } } + if err = CheckNewCollationEnable(backupMeta.GetNewCollationsEnabled(), g, mgr.GetStorage(), cfg.CheckRequirements); err != nil { + return errors.Trace(err) + } + reader := metautil.NewMetaReader(backupMeta, s, &cfg.CipherInfo) if err = client.InitBackupMeta(c, backupMeta, u, s, reader); err != nil { return errors.Trace(err) diff --git a/br/pkg/version/version.go b/br/pkg/version/version.go index 342d73d67e332c3d822abfc5032029ddb5c67082..17d8bc672829687899eec5006a0837979aa6c6aa 100644 --- a/br/pkg/version/version.go +++ b/br/pkg/version/version.go @@ -102,6 +102,7 @@ func CheckClusterVersion(ctx context.Context, client pd.Client, checker VerCheck if err := checkTiFlashVersion(s); err != nil { return errors.Trace(err) } + continue } tikvVersionString := removeVAndHash(s.Version) diff --git a/br/tests/br_check_new_collocation_enable/config/new_collation_enable_false.toml b/br/tests/br_check_new_collocation_enable/config/new_collation_enable_false.toml new file mode 100644 index 0000000000000000000000000000000000000000..dd82812d2715639a59e20fff56cafdfb003ce91b --- /dev/null +++ b/br/tests/br_check_new_collocation_enable/config/new_collation_enable_false.toml @@ -0,0 +1,16 @@ +# config of tidb + +# Schema lease duration +# There are lot of ddl in the tests, setting this +# to 360s to test whether BR is gracefully shutdown. +lease = "360s" + +new_collations_enabled_on_first_bootstrap = false + +[security] +ssl-ca = "/tmp/backup_restore_test/certs/ca.pem" +ssl-cert = "/tmp/backup_restore_test/certs/tidb.pem" +ssl-key = "/tmp/backup_restore_test/certs/tidb.key" +cluster-ssl-ca = "/tmp/backup_restore_test/certs/ca.pem" +cluster-ssl-cert = "/tmp/backup_restore_test/certs/tidb.pem" +cluster-ssl-key = "/tmp/backup_restore_test/certs/tidb.key" diff --git a/br/tests/br_check_new_collocation_enable/config/new_collation_enable_true.toml b/br/tests/br_check_new_collocation_enable/config/new_collation_enable_true.toml new file mode 100644 index 0000000000000000000000000000000000000000..d9cb1df6178f009f82e4f9c738ee7f82ad58ab2e --- /dev/null +++ b/br/tests/br_check_new_collocation_enable/config/new_collation_enable_true.toml @@ -0,0 +1,16 @@ +# config of tidb + +# Schema lease duration +# There are lot of ddl in the tests, setting this +# to 360s to test whether BR is gracefully shutdown. +lease = "360s" + +new_collations_enabled_on_first_bootstrap = true + +[security] +ssl-ca = "/tmp/backup_restore_test/certs/ca.pem" +ssl-cert = "/tmp/backup_restore_test/certs/tidb.pem" +ssl-key = "/tmp/backup_restore_test/certs/tidb.key" +cluster-ssl-ca = "/tmp/backup_restore_test/certs/ca.pem" +cluster-ssl-cert = "/tmp/backup_restore_test/certs/tidb.pem" +cluster-ssl-key = "/tmp/backup_restore_test/certs/tidb.key" diff --git a/br/tests/br_check_new_collocation_enable/run.sh b/br/tests/br_check_new_collocation_enable/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..d74262148fb5c0684822357dd9fd97641b40ba16 --- /dev/null +++ b/br/tests/br_check_new_collocation_enable/run.sh @@ -0,0 +1,102 @@ +#!/bin/sh +# +# Copyright 2019 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, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -eu +DB="$TEST_NAME" + +cur=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +source $cur/../_utils/run_services + +PROGRESS_FILE="$TEST_DIR/progress_unit_file" +rm -rf $PROGRESS_FILE + +run_sql "CREATE DATABASE $DB;" + +run_sql "CREATE TABLE $DB.usertable1 ( \ + YCSB_KEY varchar(64) NOT NULL, \ + FIELD0 varchar(1) DEFAULT NULL, \ + PRIMARY KEY (YCSB_KEY) \ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" + +run_sql "INSERT INTO $DB.usertable1 VALUES (\"a\", \"b\");" +run_sql "INSERT INTO $DB.usertable1 VALUES (\"aa\", \"b\");" + +run_sql "CREATE TABLE $DB.usertable2 ( \ + YCSB_KEY varchar(64) NOT NULL, \ + FIELD0 varchar(1) DEFAULT NULL, \ + PRIMARY KEY (YCSB_KEY) \ +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;" + +run_sql "INSERT INTO $DB.usertable2 VALUES (\"c\", \"d\");" + +# backup db +echo "backup start ... with brv4.0.8 without NewCollactionEnable" +bin/brv4.0.8 backup db --db "$DB" -s "local://$TEST_DIR/$DB" \ + --ca "$TEST_DIR/certs/ca.pem" \ + --cert "$TEST_DIR/certs/br.pem" \ + --key "$TEST_DIR/certs/br.key" \ + --pd $PD_ADDR \ + --check-requirements=false + +# restore db from v4.0.8 version without `newCollationEnable` +echo "restore start ... without NewCollactionEnable in backupmeta" +restore_fail=0 +error_str="NewCollactionEnable not found in backupmeta" +test_log="new_collotion_enable_test.log" +unset BR_LOG_TO_TERM +run_br restore db --db $DB -s "local://$TEST_DIR/$DB" --pd $PD_ADDR --log-file $test_log || restore_fail=1 +if [ $restore_fail -ne 1 ]; then + echo "TEST: [$TEST_NAME] test restore failed!" + exit 1 +fi + +if ! grep -i "$error_str" $test_log; then + echo "${error_str} not found in log" + echo "TEST: [$TEST_NAME] test restore failed!" + exit 1 +fi + +rm -rf "$test_log" + +# backup with NewCollationEable = false +echo "Restart cluster with new_collation_enable=false" +start_services --tidb-cfg $cur/config/new_collation_enable_false.toml + +echo "backup start ... witch NewCollactionEnable=false in TiDB" +run_br --pd $PD_ADDR backup db --db "$DB" -s "local://$cur/${DB}_2" + +echo "Restart cluster with new_collation_enable=true" +start_services --tidb-cfg $cur/config/new_collation_enable_true.toml + +echo "restore start ... with NewCollactionEnable=True in TiDB" +restore_fail=0 +test_log2="new_collotion_enable_test2.log" +error_str="newCollationEnable not match" +unset BR_LOG_TO_TERM +run_br restore db --db $DB -s "local://$cur/${DB}_2" --pd $PD_ADDR --log-file $test_log2 || restore_fail=1 +if [ $restore_fail -ne 1 ]; then + echo "TEST: [$TEST_NAME] test restore failed!" + exit 1 +fi + +if ! grep -i "$error_str" $test_log2; then + echo "${error_str} not found in log" + echo "TEST: [$TEST_NAME] test restore failed!" + exit 1 +fi + +rm -rf "$test_log2" +rm -rf "$cur/${DB}_2" diff --git a/br/tests/br_s3/run.sh b/br/tests/br_s3/run.sh index d0c20996db7efabb0dbe8b04ee0f03f927281c05..9cd383de4f0266bbf0d9aff8ee62003cbf36ddc9 100755 --- a/br/tests/br_s3/run.sh +++ b/br/tests/br_s3/run.sh @@ -101,6 +101,12 @@ for p in $(seq 2); do exit 1 fi + target_log="get newCollationEnable for check during restore" + if ! grep -i "$target_log" $BACKUP_LOG; then + echo "${target_log} not found in log" + exit 1 + fi + for i in $(seq $DB_COUNT); do run_sql "DROP DATABASE $DB${i};" done diff --git a/executor/brie.go b/executor/brie.go index a482e3f636814afd9b935c029b670a11c3d7a846..be4cb1a54d7df62361f5e0733776c2b829348954 100644 --- a/executor/brie.go +++ b/executor/brie.go @@ -523,6 +523,11 @@ func (gs *tidbGlueSession) CreatePlacementPolicy(ctx context.Context, policy *mo func (gs *tidbGlueSession) Close() { } +// GetGlobalVariables implements glue.Session. +func (gs *tidbGlueSession) GetGlobalVariable(name string) (string, error) { + return gs.se.GetSessionVars().GlobalVarsAccessor.GetTiDBTableValue(name) +} + // Open implements glue.Glue func (gs *tidbGlueSession) Open(string, pd.SecurityOption) (kv.Storage, error) { return gs.se.GetStore(), nil diff --git a/go.mod b/go.mod index 6fa7c92f93af803415ce1e627f09707761db5bda..de285f04e7e8fc3f16b704bea3137ae0898e550d 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c github.com/pingcap/failpoint v0.0.0-20220303073211-00fea37feb66 github.com/pingcap/fn v0.0.0-20200306044125-d5540d389059 - github.com/pingcap/kvproto v0.0.0-20220314103629-10e688307221 + github.com/pingcap/kvproto v0.0.0-20220328072018-6e75c12dbd73 github.com/pingcap/log v0.0.0-20211215031037-e024ba4eb0ee github.com/pingcap/sysutil v0.0.0-20220114020952-ea68d2dbf5b4 github.com/pingcap/tidb/parser v0.0.0-20211011031125-9b13dc409c5e diff --git a/go.sum b/go.sum index dcf0df364f78c5b401adb09572accc117b32a562..3a608b70b008da93bc2d923a0e25cc5553d6375b 100644 --- a/go.sum +++ b/go.sum @@ -633,8 +633,8 @@ github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17Xtb github.com/pingcap/kvproto v0.0.0-20191211054548-3c6b38ea5107/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= github.com/pingcap/kvproto v0.0.0-20220302110454-c696585a961b/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/pingcap/kvproto v0.0.0-20220304032058-ccd676426a27/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= -github.com/pingcap/kvproto v0.0.0-20220314103629-10e688307221 h1:QiHOVihPED67vDEZE6kP3cGrS55U1+QXbSTahGaEyOI= -github.com/pingcap/kvproto v0.0.0-20220314103629-10e688307221/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= +github.com/pingcap/kvproto v0.0.0-20220328072018-6e75c12dbd73 h1:jKixsi6Iw00hL0+o23hmr8BNzlsQP9pShHTOwyuf/Os= +github.com/pingcap/kvproto v0.0.0-20220328072018-6e75c12dbd73/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20200511115504-543df19646ad/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/log v0.0.0-20210625125904-98ed8e2eb1c7/go.mod h1:8AanEdAHATuRurdGxZXBz0At+9avep+ub7U1AGYLIMM=