diff --git a/br/pkg/conn/conn.go b/br/pkg/conn/conn.go index 48d45e6070ffa..c22c71e075b30 100755 --- a/br/pkg/conn/conn.go +++ b/br/pkg/conn/conn.go @@ -291,6 +291,15 @@ func NewMgr( if err != nil { return nil, errors.Trace(err) } + // we must check tidb(tikv version) any time after concurrent ddl feature implemented in v6.2. + // when tidb < 6.2 we need set EnableConcurrentDDL false to make ddl works. + // we will keep this check until 7.0, which allow the breaking changes. + // NOTE: must call it after domain created! + // FIXME: remove this check in v7.0 + err = version.CheckClusterVersion(ctx, controller.GetPDClient(), version.CheckVersionForDDL) + if err != nil { + return nil, errors.Annotate(err, "unable to check cluster version for ddl") + } } mgr := &Mgr{ diff --git a/br/pkg/version/version.go b/br/pkg/version/version.go index 17d8bc6728296..85d064bc2717e 100644 --- a/br/pkg/version/version.go +++ b/br/pkg/version/version.go @@ -18,6 +18,11 @@ import ( "github.com/pingcap/tidb/br/pkg/logutil" "github.com/pingcap/tidb/br/pkg/utils" "github.com/pingcap/tidb/br/pkg/version/build" +<<<<<<< HEAD +======= + "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/util/engine" +>>>>>>> 28a8ffcf6... br: fix compatibility issue with concurrent ddl (#36474) pd "github.com/tikv/pd/client" "go.uber.org/zap" ) @@ -129,6 +134,52 @@ func CheckVersionForBackup(backupVersion *semver.Version) VerChecker { } } +<<<<<<< HEAD +======= +// CheckVersionForBRPiTR checks whether version of the cluster and BR-pitr itself is compatible. +// Note: BR'version >= 6.1.0 at least in this function +func CheckVersionForBRPiTR(s *metapb.Store, tikvVersion *semver.Version) error { + BRVersion, err := semver.NewVersion(removeVAndHash(build.ReleaseVersion)) + if err != nil { + return errors.Annotatef(berrors.ErrVersionMismatch, "%s: invalid version, please recompile using `git fetch origin --tags && make build`", err) + } + + // tikvVersion should at least 6.1.0 + if tikvVersion.Major < 6 || (tikvVersion.Major == 6 && tikvVersion.Minor == 0) { + return errors.Annotatef(berrors.ErrVersionMismatch, "TiKV node %s version %s is too low when use PiTR, please update tikv's version to at least v6.1.0(v6.2.0+ recommanded)", + s.Address, tikvVersion) + } + + // The versions of BR and TiKV should be the same when use BR 6.1.0 + if BRVersion.Major == 6 && BRVersion.Minor == 1 { + if tikvVersion.Major != 6 || tikvVersion.Minor != 1 { + return errors.Annotatef(berrors.ErrVersionMismatch, "TiKV node %s version %s and BR %s version mismatch when use PiTR v6.1.0, please use the same version of BR", + s.Address, tikvVersion, build.ReleaseVersion) + } + } else { + // If BRVersion > v6.1.0, the version of TiKV should be at least v6.2.0 + if tikvVersion.Major == 6 && tikvVersion.Minor <= 1 { + return errors.Annotatef(berrors.ErrVersionMismatch, "TiKV node %s version %s and BR %s version mismatch when use PiTR v6.2.0+, please use the tikv with version v6.2.0+", + s.Address, tikvVersion, build.ReleaseVersion) + } + } + + return nil +} + +// CheckVersionForDDL checks whether we use queue or table to execute ddl during restore. +func CheckVersionForDDL(s *metapb.Store, tikvVersion *semver.Version) error { + // use tikvVersion instead of tidbVersion since br doesn't have mysql client to connect tidb. + requireVersion := semver.New("6.2.0-alpha") + if tikvVersion.Compare(*requireVersion) < 0 { + log.Info("detected the old version of tidb cluster. set enable concurrent ddl to false") + variable.EnableConcurrentDDL.Store(false) + return nil + } + return nil +} + +>>>>>>> 28a8ffcf6... br: fix compatibility issue with concurrent ddl (#36474) // CheckVersionForBR checks whether version of the cluster and BR itself is compatible. func CheckVersionForBR(s *metapb.Store, tikvVersion *semver.Version) error { BRVersion, err := semver.NewVersion(removeVAndHash(build.ReleaseVersion)) diff --git a/br/pkg/version/version_test.go b/br/pkg/version/version_test.go index 84ffd74849aaa..5c8ee0debabfa 100644 --- a/br/pkg/version/version_test.go +++ b/br/pkg/version/version_test.go @@ -13,6 +13,7 @@ import ( "github.com/coreos/go-semver/semver" "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/br/pkg/version/build" + "github.com/pingcap/tidb/sessionctx/variable" "github.com/stretchr/testify/require" pd "github.com/tikv/pd/client" ) @@ -193,6 +194,55 @@ func TestCheckClusterVersion(t *testing.T) { require.Error(t, err) } + { + mock.getAllStores = func() []*metapb.Store { + return []*metapb.Store{{Version: "v6.4.0"}} + } + originVal := variable.EnableConcurrentDDL.Load() + err := CheckClusterVersion(context.Background(), &mock, CheckVersionForDDL) + require.NoError(t, err) + require.Equal(t, originVal, variable.EnableConcurrentDDL.Load()) + } + + { + mock.getAllStores = func() []*metapb.Store { + return []*metapb.Store{{Version: "v6.2.0"}} + } + originVal := variable.EnableConcurrentDDL.Load() + err := CheckClusterVersion(context.Background(), &mock, CheckVersionForDDL) + require.NoError(t, err) + require.Equal(t, originVal, variable.EnableConcurrentDDL.Load()) + } + + { + mock.getAllStores = func() []*metapb.Store { + return []*metapb.Store{{Version: "v6.2.0-alpha"}} + } + originVal := variable.EnableConcurrentDDL.Load() + err := CheckClusterVersion(context.Background(), &mock, CheckVersionForDDL) + require.NoError(t, err) + require.Equal(t, originVal, variable.EnableConcurrentDDL.Load()) + } + + { + mock.getAllStores = func() []*metapb.Store { + return []*metapb.Store{{Version: "v6.1.0"}} + } + variable.EnableConcurrentDDL.Store(true) + err := CheckClusterVersion(context.Background(), &mock, CheckVersionForDDL) + require.NoError(t, err) + require.False(t, variable.EnableConcurrentDDL.Load()) + } + + { + mock.getAllStores = func() []*metapb.Store { + return []*metapb.Store{{Version: "v5.4.0"}} + } + variable.EnableConcurrentDDL.Store(true) + err := CheckClusterVersion(context.Background(), &mock, CheckVersionForDDL) + require.NoError(t, err) + require.False(t, variable.EnableConcurrentDDL.Load()) + } } func TestCompareVersion(t *testing.T) { diff --git a/br/tests/br_rawkv/run.sh b/br/tests/br_rawkv/run.sh index 97450d3e65fc7..ffda37f1ad5e8 100755 --- a/br/tests/br_rawkv/run.sh +++ b/br/tests/br_rawkv/run.sh @@ -53,7 +53,7 @@ test_full_rawkv() { checksum_full=$(checksum $check_range_start $check_range_end) # backup current state of key-values # raw backup is not working with range [nil, nil]. TODO: fix it. - run_br --pd $PD_ADDR backup raw -s "local://$BACKUP_FULL" --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" --start $check_range_start --format hex + run_br --pd $PD_ADDR backup raw -s "local://$BACKUP_FULL" --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" --start $check_range_start --end $check_range_end --format hex clean $check_range_start $check_range_end # Ensure the data is deleted @@ -63,7 +63,7 @@ test_full_rawkv() { fail_and_exit fi - run_br --pd $PD_ADDR restore raw -s "local://$BACKUP_FULL" --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" --start $check_range_start --format hex + run_br --pd $PD_ADDR restore raw -s "local://$BACKUP_FULL" --crypter.method "aes128-ctr" --crypter.key "0123456789abcdef0123456789abcdef" --start $check_range_start --end $check_range_end --format hex checksum_new=$(checksum $check_range_start $check_range_end) if [ "$checksum_new" != "$checksum_full" ];then echo "failed to restore"