diff --git a/br/pkg/gluetidb/BUILD.bazel b/br/pkg/gluetidb/BUILD.bazel index b639da451010d..baebdba642728 100644 --- a/br/pkg/gluetidb/BUILD.bazel +++ b/br/pkg/gluetidb/BUILD.bazel @@ -34,6 +34,7 @@ go_test( deps = [ "//br/pkg/glue", "//pkg/parser/model", + "//pkg/session", "//pkg/testkit", "//pkg/types", "@com_github_stretchr_testify//require", diff --git a/br/pkg/gluetidb/glue.go b/br/pkg/gluetidb/glue.go index 69971a52bd0d8..d7d5c907fddff 100644 --- a/br/pkg/gluetidb/glue.go +++ b/br/pkg/gluetidb/glue.go @@ -4,6 +4,7 @@ package gluetidb import ( "context" + "sync" "time" "github.com/pingcap/errors" @@ -40,14 +41,17 @@ func New() Glue { conf.Log.EnableSlowLog.Store(false) conf.TiKVClient.CoprReqTimeout = 1800 * time.Second }) - return Glue{} + return Glue{ + startDomainMu: &sync.Mutex{}, + } } // Glue is an implementation of glue.Glue using a new TiDB session. type Glue struct { glue.StdIOGlue - tikvGlue gluetikv.Glue + tikvGlue gluetikv.Glue + startDomainMu *sync.Mutex } type tidbSession struct { @@ -55,13 +59,13 @@ type tidbSession struct { } // GetDomain implements glue.Glue. -func (Glue) GetDomain(store kv.Storage) (*domain.Domain, error) { +func (g Glue) GetDomain(store kv.Storage) (*domain.Domain, error) { existDom, _ := session.GetDomain(nil) - initStatsSe, err := session.CreateSession(store) + initStatsSe, err := g.createTypesSession(store) if err != nil { return nil, errors.Trace(err) } - se, err := session.CreateSession(store) + se, err := g.createTypesSession(store) if err != nil { return nil, errors.Trace(err) } @@ -84,8 +88,8 @@ func (Glue) GetDomain(store kv.Storage) (*domain.Domain, error) { } // CreateSession implements glue.Glue. -func (Glue) CreateSession(store kv.Storage) (glue.Session, error) { - se, err := session.CreateSession(store) +func (g Glue) CreateSession(store kv.Storage) (glue.Session, error) { + se, err := g.createTypesSession(store) if err != nil { return nil, errors.Trace(err) } @@ -95,6 +99,27 @@ func (Glue) CreateSession(store kv.Storage) (glue.Session, error) { return tiSession, nil } +func (g Glue) startDomainAsNeeded(store kv.Storage) error { + g.startDomainMu.Lock() + defer g.startDomainMu.Unlock() + existDom, _ := session.GetDomain(nil) + if existDom != nil { + return nil + } + dom, err := session.GetDomain(store) + if err != nil { + return err + } + return dom.Start() +} + +func (g Glue) createTypesSession(store kv.Storage) (sessiontypes.Session, error) { + if err := g.startDomainAsNeeded(store); err != nil { + return nil, errors.Trace(err) + } + return session.CreateSession(store) +} + // Open implements glue.Glue. func (g Glue) Open(path string, option pd.SecurityOption) (kv.Storage, error) { return g.tikvGlue.Open(path, option) @@ -122,7 +147,7 @@ func (g Glue) GetVersion() string { // UseOneShotSession implements glue.Glue. func (g Glue) UseOneShotSession(store kv.Storage, closeDomain bool, fn func(glue.Session) error) error { - se, err := session.CreateSession(store) + se, err := g.createTypesSession(store) if err != nil { return errors.Trace(err) } @@ -133,7 +158,7 @@ func (g Glue) UseOneShotSession(store kv.Storage, closeDomain bool, fn func(glue se.Close() log.Info("one shot session closed") }() - // dom will be created during session.CreateSession. + // dom will be created during create session. dom, err := session.GetDomain(store) if err != nil { return errors.Trace(err) diff --git a/br/pkg/gluetidb/glue_test.go b/br/pkg/gluetidb/glue_test.go index 1813a7b357b16..5c7eb6a0cb598 100644 --- a/br/pkg/gluetidb/glue_test.go +++ b/br/pkg/gluetidb/glue_test.go @@ -20,6 +20,7 @@ import ( "github.com/pingcap/tidb/br/pkg/glue" "github.com/pingcap/tidb/pkg/parser/model" + "github.com/pingcap/tidb/pkg/session" "github.com/pingcap/tidb/pkg/testkit" "github.com/pingcap/tidb/pkg/types" "github.com/stretchr/testify/require" @@ -27,14 +28,29 @@ import ( func TestTheSessionIsoation(t *testing.T) { req := require.New(t) - store := testkit.CreateMockStore(t) + store, dom := session.CreateStoreAndBootstrap(t) ctx := context.Background() - g := Glue{} - session, err := g.CreateSession(store) + // we want to test glue start domain explicitly, so close it first. + dom.Close() + g := New() + glueSe, err := g.CreateSession(store) req.NoError(err) + t.Cleanup(func() { + existDom, _ := session.GetDomain(nil) + if existDom != nil { + existDom.Close() + } + }) + + require.NoError(t, glueSe.CreateDatabase(ctx, &model.DBInfo{ + Name: model.NewCIStr("test_db"), + })) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test_db") + tk.MustExec("create table t(id int)") - req.NoError(session.ExecuteInternal(ctx, "use test;")) + req.NoError(glueSe.ExecuteInternal(ctx, "use test;")) infos := []*model.TableInfo{} infos = append(infos, &model.TableInfo{ Name: model.NewCIStr("tables_1"), @@ -75,12 +91,12 @@ func TestTheSessionIsoation(t *testing.T) { }, } for _, pinfo := range polices { - before := session.(*tidbSession).se.GetInfoSchema().SchemaMetaVersion() - req.NoError(session.CreatePlacementPolicy(ctx, pinfo)) - after := session.(*tidbSession).se.GetInfoSchema().SchemaMetaVersion() + before := glueSe.(*tidbSession).se.GetInfoSchema().SchemaMetaVersion() + req.NoError(glueSe.CreatePlacementPolicy(ctx, pinfo)) + after := glueSe.(*tidbSession).se.GetInfoSchema().SchemaMetaVersion() req.Greater(after, before) } - req.NoError(session.(glue.BatchCreateTableSession).CreateTables(ctx, map[string][]*model.TableInfo{ + req.NoError(glueSe.(glue.BatchCreateTableSession).CreateTables(ctx, map[string][]*model.TableInfo{ "test": infos, })) }