Skip to content

Commit

Permalink
txn: optimize point get with tso MaxUint64 path in txn provider (#36949)
Browse files Browse the repository at this point in the history
close #36951
  • Loading branch information
lcwangchao authored Aug 8, 2022
1 parent 3a95e52 commit 94c118b
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
23 changes: 19 additions & 4 deletions sessiontxn/isolation/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ type baseTxnContextProvider struct {
txn kv.Transaction
isTxnPrepared bool
enterNewTxnType sessiontxn.EnterNewTxnType
// constStartTS is only used by point get max ts optimization currently.
// When constStartTS != 0, we use constStartTS directly without fetching it from tso.
// To save the cpu cycles `PrepareTSFuture` will also not be called when warmup (postpone to activate txn).
constStartTS uint64
}

// OnInitialize is the hook that should be called when enter a new txn with this provider
Expand Down Expand Up @@ -222,6 +226,12 @@ func (p *baseTxnContextProvider) ActivateTxn() (kv.Transaction, error) {
return nil, err
}

if p.constStartTS != 0 {
if err := p.replaceTxnTsFuture(sessiontxn.ConstantFuture(p.constStartTS)); err != nil {
return nil, err
}
}

txnFuture := p.sctx.GetPreparedTxnFuture()
txn, err := txnFuture.Wait(p.ctx, p.sctx)
if err != nil {
Expand Down Expand Up @@ -277,7 +287,7 @@ func (p *baseTxnContextProvider) prepareTxn() error {
}

if snapshotTS := p.sctx.GetSessionVars().SnapshotTS; snapshotTS != 0 {
return p.prepareTxnWithTS(snapshotTS)
return p.replaceTxnTsFuture(sessiontxn.ConstantFuture(snapshotTS))
}

future := newOracleFuture(p.ctx, p.sctx, p.sctx.GetSessionVars().TxnCtx.TxnScope)
Expand All @@ -296,8 +306,13 @@ func (p *baseTxnContextProvider) prepareTxnWithOracleTS() error {
return p.replaceTxnTsFuture(future)
}

func (p *baseTxnContextProvider) prepareTxnWithTS(ts uint64) error {
return p.replaceTxnTsFuture(sessiontxn.ConstantFuture(ts))
func (p *baseTxnContextProvider) forcePrepareConstStartTS(ts uint64) error {
if p.txn != nil {
return errors.New("cannot force prepare const start ts because txn is active")
}
p.constStartTS = ts
p.isTxnPrepared = true
return nil
}

func (p *baseTxnContextProvider) replaceTxnTsFuture(future oracle.Future) error {
Expand Down Expand Up @@ -332,7 +347,7 @@ func (p *baseTxnContextProvider) isBeginStmtWithStaleRead() bool {

// AdviseWarmup provides warmup for inner state
func (p *baseTxnContextProvider) AdviseWarmup() error {
if p.isBeginStmtWithStaleRead() {
if p.isTxnPrepared || p.isBeginStmtWithStaleRead() {
// When executing `START TRANSACTION READ ONLY AS OF ...` no need to warmUp
return nil
}
Expand Down
32 changes: 29 additions & 3 deletions sessiontxn/isolation/optimistic.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
// OptimisticTxnContextProvider provides txn context for optimistic transaction
type OptimisticTxnContextProvider struct {
baseTxnContextProvider
optimizeWithMaxTS bool
}

// NewOptimisticTxnContextProvider returns a new OptimisticTxnContextProvider
Expand Down Expand Up @@ -89,10 +90,28 @@ func isOptimisticTxnRetryable(sessVars *variable.SessionVars, tp sessiontxn.Ente
return false
}

// GetStmtReadTS returns the read timestamp used by select statement (not for select ... for update)
func (p *OptimisticTxnContextProvider) GetStmtReadTS() (uint64, error) {
// If `math.MaxUint64` is used for point get optimization, it is not necessary to activate the txn.
// Just return `math.MaxUint64` to save the performance.
if p.optimizeWithMaxTS {
return math.MaxUint64, nil
}
return p.baseTxnContextProvider.GetStmtReadTS()
}

// GetStmtForUpdateTS returns the read timestamp used by select statement (not for select ... for update)
func (p *OptimisticTxnContextProvider) GetStmtForUpdateTS() (uint64, error) {
if p.optimizeWithMaxTS {
return math.MaxUint64, nil
}
return p.baseTxnContextProvider.GetStmtForUpdateTS()
}

// AdviseOptimizeWithPlan providers optimization according to the plan
// It will use MaxTS as the startTS in autocommit txn for some plans.
func (p *OptimisticTxnContextProvider) AdviseOptimizeWithPlan(plan interface{}) (err error) {
if p.isTidbSnapshotEnabled() || p.isBeginStmtWithStaleRead() {
if p.optimizeWithMaxTS || p.isTidbSnapshotEnabled() || p.isBeginStmtWithStaleRead() {
return nil
}

Expand All @@ -116,10 +135,17 @@ func (p *OptimisticTxnContextProvider) AdviseOptimizeWithPlan(plan interface{})
zap.Uint64("conn", sessVars.ConnectionID),
zap.String("text", sessVars.StmtCtx.OriginalSQL),
)
if err = p.prepareTxnWithTS(math.MaxUint64); err != nil {
return err

if err = p.forcePrepareConstStartTS(math.MaxUint64); err != nil {
logutil.BgLogger().Error("failed init txnStartTS with MaxUint64",
zap.Error(err),
zap.Uint64("conn", sessVars.ConnectionID),
zap.String("text", sessVars.StmtCtx.OriginalSQL),
)
return nil
}

p.optimizeWithMaxTS = true
if sessVars.StmtCtx.Priority == mysql.NoPriority {
sessVars.StmtCtx.Priority = kv.PriorityHigh
}
Expand Down

0 comments on commit 94c118b

Please sign in to comment.