diff --git a/executor/builder.go b/executor/builder.go index 3588a80bfd75f..1912f17eb5458 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -94,6 +94,7 @@ type executorBuilder struct { readReplicaScope string inUpdateStmt bool inDeleteStmt bool + inInsertStmt bool } // CTEStorages stores resTbl and iterInTbl for CTEExec. @@ -795,6 +796,7 @@ func (b *executorBuilder) buildSetConfig(v *plannercore.SetConfig) Executor { } func (b *executorBuilder) buildInsert(v *plannercore.Insert) Executor { + b.inInsertStmt = true if v.SelectPlan != nil { // Try to update the forUpdateTS for insert/replace into select statements. // Set the selectPlan parameter to nil to make it always update the forUpdateTS. @@ -1420,6 +1422,12 @@ func (b *executorBuilder) buildProjection(v *plannercore.PhysicalProjection) Exe if int64(v.StatsCount()) < int64(b.ctx.GetSessionVars().MaxChunkSize) { e.numWorkers = 0 } + + // Use un-parallel projection for query that write on memdb to avoid data race. + // See also https://github.com/pingcap/tidb/issues/26832 + if b.inUpdateStmt || b.inDeleteStmt || b.inInsertStmt || b.hasLock { + e.numWorkers = 0 + } return e } @@ -1936,6 +1944,7 @@ func (b *executorBuilder) buildSplitRegion(v *plannercore.SplitRegion) Executor } func (b *executorBuilder) buildUpdate(v *plannercore.Update) Executor { + b.inUpdateStmt = true tblID2table := make(map[int64]table.Table, len(v.TblColPosInfos)) multiUpdateOnSameTable := make(map[int64]bool) for _, info := range v.TblColPosInfos { @@ -1976,7 +1985,6 @@ func (b *executorBuilder) buildUpdate(v *plannercore.Update) Executor { if b.err != nil { return nil } - b.inUpdateStmt = true updateExec := &UpdateExec{ baseExecutor: base, OrderedList: v.OrderedList, @@ -2009,6 +2017,7 @@ func getAssignFlag(ctx sessionctx.Context, v *plannercore.Update, schemaLen int) } func (b *executorBuilder) buildDelete(v *plannercore.Delete) Executor { + b.inDeleteStmt = true tblID2table := make(map[int64]table.Table, len(v.TblColPosInfos)) for _, info := range v.TblColPosInfos { tblID2table[info.TblID], _ = b.is.TableByID(info.TblID) @@ -2021,7 +2030,6 @@ func (b *executorBuilder) buildDelete(v *plannercore.Delete) Executor { if b.err != nil { return nil } - b.inDeleteStmt = true base := newBaseExecutor(b.ctx, v.Schema(), v.ID(), selExec) base.initCap = chunk.ZeroCapacity deleteExec := &DeleteExec{