Skip to content

Commit

Permalink
bindinfo: refactor some codes in bindinfo package (#33094)
Browse files Browse the repository at this point in the history
  • Loading branch information
Reminiscent authored Mar 15, 2022
1 parent 00e9622 commit e87bb52
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 21 deletions.
29 changes: 24 additions & 5 deletions bindinfo/bind_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ func (b *Binding) IsBindingEnabled() bool {
return b.Status == Enabled || b.Status == Using
}

// IsBindingAvailable returns whether the binding is available.
// The available means the binding can be used or can be converted into a usable status.
// It includes the 'Enabled', 'Using' and 'Disabled' status.
func (b *Binding) IsBindingAvailable() bool {
return b.IsBindingEnabled() || b.Status == Disabled
}

// SinceUpdateTime returns the duration since last update time. Export for test.
func (b *Binding) SinceUpdateTime() (time.Duration, error) {
updateTime, err := b.UpdateTime.GoTime(time.Local)
Expand All @@ -104,8 +111,8 @@ type BindRecord struct {
Bindings []Binding
}

// HasUsingBinding checks if there are any using bindings in bind record.
func (br *BindRecord) HasUsingBinding() bool {
// HasEnabledBinding checks if there are any enabled bindings in bind record.
func (br *BindRecord) HasEnabledBinding() bool {
for _, binding := range br.Bindings {
if binding.IsBindingEnabled() {
return true
Expand All @@ -114,9 +121,21 @@ func (br *BindRecord) HasUsingBinding() bool {
return false
}

// FindUsingBinding gets the using binding.
// There is at most one binding that can be used now
func (br *BindRecord) FindUsingBinding() *Binding {
// HasAvailableBinding checks if there are any available bindings in bind record.
// The available means the binding can be used or can be converted into a usable status.
// It includes the 'Enabled', 'Using' and 'Disabled' status.
func (br *BindRecord) HasAvailableBinding() bool {
for _, binding := range br.Bindings {
if binding.IsBindingAvailable() {
return true
}
}
return false
}

// FindEnabledBinding gets the enabled binding.
// There is at most one binding that can be used now.
func (br *BindRecord) FindEnabledBinding() *Binding {
for _, binding := range br.Bindings {
if binding.IsBindingEnabled() {
return &binding
Expand Down
16 changes: 8 additions & 8 deletions bindinfo/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func (h *BindHandle) Update(fullLoad bool) (err error) {
// When the memory capacity of bing_cache is not enough,
// there will be some memory-related errors in multiple places.
// Only needs to be handled once.
logutil.BgLogger().Warn("[sql-bind] ", zap.Error(err))
logutil.BgLogger().Warn("[sql-bind] BindHandle.Update", zap.Error(memExceededErr))
}
return nil
}
Expand Down Expand Up @@ -280,7 +280,7 @@ func (h *BindHandle) AddBindRecord(sctx sessionctx.Context, record *BindRecord)
if oldRecord != nil {
binding := oldRecord.FindBinding(record.Bindings[0].ID)
if binding != nil {
// There is already a binding with status `Using`, `PendingVerify` or `Rejected`, we could directly cancel the job.
// There is already a binding with status `Enabled`, `Disabled`, `PendingVerify` or `Rejected`, we could directly cancel the job.
if record.Bindings[0].Status == PendingVerify {
return nil
}
Expand Down Expand Up @@ -595,30 +595,30 @@ func (h *BindHandle) newBindRecord(row chunk.Row) (string, *BindRecord, error) {
func (h *BindHandle) setBindRecord(hash string, meta *BindRecord) {
newCache, err0 := h.bindInfo.Value.Load().(*bindCache).Copy()
if err0 != nil {
logutil.BgLogger().Warn("[sql-bind] ", zap.Error(err0))
logutil.BgLogger().Warn("[sql-bind] BindHandle.setBindRecord", zap.Error(err0))
}
oldRecord := newCache.GetBindRecord(hash, meta.OriginalSQL, meta.Db)
err1 := newCache.SetBindRecord(hash, meta)
if err1 != nil && err0 == nil {
logutil.BgLogger().Warn("[sql-bind] ", zap.Error(err1))
logutil.BgLogger().Warn("[sql-bind] BindHandle.setBindRecord", zap.Error(err1))
}
h.bindInfo.Value.Store(newCache)
updateMetrics(metrics.ScopeGlobal, oldRecord, meta, false)
}

// appendBindRecord addes the BindRecord to the cache, all the stale BindRecords are
// appendBindRecord adds the BindRecord to the cache, all the stale BindRecords are
// removed from the cache after this operation.
func (h *BindHandle) appendBindRecord(hash string, meta *BindRecord) {
newCache, err0 := h.bindInfo.Value.Load().(*bindCache).Copy()
if err0 != nil {
logutil.BgLogger().Warn("[sql-bind] ", zap.Error(err0))
logutil.BgLogger().Warn("[sql-bind] BindHandle.appendBindRecord", zap.Error(err0))
}
oldRecord := newCache.GetBindRecord(hash, meta.OriginalSQL, meta.Db)
newRecord := merge(oldRecord, meta)
err1 := newCache.SetBindRecord(hash, newRecord)
if err1 != nil && err0 == nil {
// Only need to handle the error once.
logutil.BgLogger().Warn("[sql-bind] ", zap.Error(err1))
logutil.BgLogger().Warn("[sql-bind] BindHandle.appendBindRecord", zap.Error(err1))
}
h.bindInfo.Value.Store(newCache)
updateMetrics(metrics.ScopeGlobal, oldRecord, newRecord, false)
Expand Down Expand Up @@ -783,7 +783,7 @@ func (h *BindHandle) CaptureBaselines() {
}
dbName := utilparser.GetDefaultDB(stmt, bindableStmt.Schema)
normalizedSQL, digest := parser.NormalizeDigest(utilparser.RestoreWithDefaultDB(stmt, dbName, bindableStmt.Query))
if r := h.GetBindRecord(digest.String(), normalizedSQL, dbName); r != nil && r.HasUsingBinding() {
if r := h.GetBindRecord(digest.String(), normalizedSQL, dbName); r != nil && r.HasAvailableBinding() {
continue
}
bindSQL := GenerateBindSQL(context.TODO(), stmt, bindableStmt.PlanHint, true, dbName)
Expand Down
2 changes: 1 addition & 1 deletion bindinfo/session_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (h *SessionHandle) appendBindRecord(hash string, meta *BindRecord) {
oldRecord := h.ch.GetBindRecord(hash, meta.OriginalSQL, meta.Db)
err := h.ch.SetBindRecord(hash, meta)
if err != nil {
logutil.BgLogger().Warn("[sql-bind] ", zap.Error(err))
logutil.BgLogger().Warn("[sql-bind] SessionHandle.appendBindRecord", zap.Error(err))
}
updateMetrics(metrics.ScopeSession, oldRecord, meta, false)
}
Expand Down
12 changes: 6 additions & 6 deletions planner/core/common_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,9 +405,9 @@ func GetBindSQL4PlanCache(sctx sessionctx.Context, preparedStmt *CachedPrepareSt
sessionHandle := sctx.Value(bindinfo.SessionBindInfoKeyType).(*bindinfo.SessionHandle)
bindRecord := sessionHandle.GetBindRecord(preparedStmt.SQLDigest4PC, preparedStmt.NormalizedSQL4PC, "")
if bindRecord != nil {
usingBinding := bindRecord.FindUsingBinding()
if usingBinding != nil {
return usingBinding.BindSQL
enabledBinding := bindRecord.FindEnabledBinding()
if enabledBinding != nil {
return enabledBinding.BindSQL
}
}
globalHandle := domain.GetDomain(sctx).BindHandle()
Expand All @@ -416,9 +416,9 @@ func GetBindSQL4PlanCache(sctx sessionctx.Context, preparedStmt *CachedPrepareSt
}
bindRecord = globalHandle.GetBindRecord(preparedStmt.SQLDigest4PC, preparedStmt.NormalizedSQL4PC, "")
if bindRecord != nil {
usingBinding := bindRecord.FindUsingBinding()
if usingBinding != nil {
return usingBinding.BindSQL
enabledBinding := bindRecord.FindEnabledBinding()
if enabledBinding != nil {
return enabledBinding.BindSQL
}
}
return ""
Expand Down
2 changes: 1 addition & 1 deletion planner/optimize.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ func getBindRecord(ctx sessionctx.Context, stmt ast.StmtNode) (*bindinfo.BindRec
sessionHandle := ctx.Value(bindinfo.SessionBindInfoKeyType).(*bindinfo.SessionHandle)
bindRecord := sessionHandle.GetBindRecord(hash, normalizedSQL, "")
if bindRecord != nil {
if bindRecord.HasUsingBinding() {
if bindRecord.HasEnabledBinding() {
return bindRecord, metrics.ScopeSession, nil
}
return nil, "", nil
Expand Down
10 changes: 10 additions & 0 deletions session/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,8 @@ const (
version83 = 83
// version84 adds the tables mysql.stats_meta_history
version84 = 84
// version85 updates bindings with status 'using' in mysql.bind_info table to 'enabled' status
version85 = 85
)

// currentBootstrapVersion is defined as a variable, so we can modify its value for testing.
Expand Down Expand Up @@ -673,6 +675,7 @@ var (
upgradeToVer82,
upgradeToVer83,
upgradeToVer84,
upgradeToVer85,
}
)

Expand Down Expand Up @@ -1742,6 +1745,13 @@ func upgradeToVer84(s Session, ver int64) {
doReentrantDDL(s, CreateStatsMetaHistory)
}

func upgradeToVer85(s Session, ver int64) {
if ver >= version85 {
return
}
mustExecute(s, fmt.Sprintf("UPDATE HIGH_PRIORITY mysql.bind_info SET status= '%s' WHERE status = '%s'", bindinfo.Enabled, bindinfo.Using))
}

func writeOOMAction(s Session) {
comment := "oom-action is `log` by default in v3.0.x, `cancel` by default in v4.0.11+"
mustExecute(s, `INSERT HIGH_PRIORITY INTO %n.%n VALUES (%?, %?, %?) ON DUPLICATE KEY UPDATE VARIABLE_VALUE= %?`,
Expand Down
24 changes: 24 additions & 0 deletions session/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1070,3 +1070,27 @@ func TestIndexMergeUpgradeFrom400To540(t *testing.T) {
}()
}
}

func TestUpgradeToVer85(t *testing.T) {
ctx := context.Background()
store, dom := createStoreAndBootstrap(t)
defer func() { require.NoError(t, store.Close()) }()
defer dom.Close()
se := createSessionAndSetID(t, store)
mustExec(t, se, `insert into mysql.bind_info values('select * from t', 'select /*+ use_index(t, idx_a)*/ * from t', 'test', 'using', '2021-01-04 14:50:58.257', '2021-01-04 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`)
mustExec(t, se, `insert into mysql.bind_info values('select * from t1', 'select /*+ use_index(t1, idx_a)*/ * from t1', 'test', 'enabled', '2021-01-05 14:50:58.257', '2021-01-05 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`)
mustExec(t, se, `insert into mysql.bind_info values('select * from t2', 'select /*+ use_index(t2, idx_a)*/ * from t2', 'test', 'disabled', '2021-01-06 14:50:58.257', '2021-01-06 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`)
mustExec(t, se, `insert into mysql.bind_info values('select * from t3', 'select /*+ use_index(t3, idx_a)*/ * from t3', 'test', 'deleted', '2021-01-07 14:50:58.257', '2021-01-07 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`)
mustExec(t, se, `insert into mysql.bind_info values('select * from t4', 'select /*+ use_index(t4, idx_a)*/ * from t4', 'test', 'invalid', '2021-01-08 14:50:58.257', '2021-01-08 14:50:58.257', 'utf8', 'utf8_general_ci', 'manual')`)
upgradeToVer85(se, version84)

r := mustExec(t, se, `select count(*) from mysql.bind_info where status = 'enabled'`)
req := r.NewChunk(nil)
require.NoError(t, r.Next(ctx, req))
require.Equal(t, 1, req.NumRows())
row := req.GetRow(0)
require.Equal(t, int64(2), row.GetInt64(0))

require.NoError(t, r.Close())
mustExec(t, se, "delete from mysql.bind_info where default_db = 'test'")
}

0 comments on commit e87bb52

Please sign in to comment.