Skip to content

Commit 084c62f

Browse files
craig[bot]kyle-a-wongmgartner
committed
139279: sqlstats: fix race condition in ss_mem_iterator r=kyle-a-wong a=kyle-a-wong StmtStatsIterator.Next() copies the next statement stats info into a new CollectedStatementStatistics object, but the slice fields of stmtStats.mu.data are not copied explicitly. This makes them susecptible to race conditions, as seen in #138224. To fix, all slice fields in the StatementStatistics are explicitly copied, using a new util.CopySlice function. Fixes: #138224 Epic: none Release note: none 140035: opt: reduce `opt.ColSet` allocs when exploring partial index scans r=mgartner a=mgartner When exploring a partial index scan, we previously built a set of columns held constant by partial index predicate, and then built another set of those columns that are not composite key encoded. Now, instead of building the second set, we remove columns from the first. This will reduce allocations in the case where the constant column IDs are larger than 128. Epic: None Release note: None Co-authored-by: Kyle Wong <[email protected]> Co-authored-by: Marcus Gartner <[email protected]>
3 parents 49d65d3 + 3ea3deb + c891e96 commit 084c62f

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

pkg/sql/opt/xform/scan_index_iter.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -364,15 +364,14 @@ func (it *scanIndexIter) filtersImplyPredicate(
364364
// the given filters and of types that do not have composite encodings.
365365
func (it *scanIndexIter) extractConstNonCompositeColumns(f memo.FiltersExpr) opt.ColSet {
366366
constCols := memo.ExtractConstColumns(it.e.ctx, f, it.evalCtx)
367-
var constNonCompositeCols opt.ColSet
368367
for col, ok := constCols.Next(0); ok; col, ok = constCols.Next(col + 1) {
369368
ord := it.tabMeta.MetaID.ColumnOrdinal(col)
370369
typ := it.tabMeta.Table.Column(ord).DatumType()
371-
if !colinfo.CanHaveCompositeKeyEncoding(typ) {
372-
constNonCompositeCols.Add(col)
370+
if colinfo.CanHaveCompositeKeyEncoding(typ) {
371+
constCols.Remove(col)
373372
}
374373
}
375-
return constNonCompositeCols
374+
return constCols
376375
}
377376

378377
// buildConstProjectionsFromPredicate builds a ProjectionsExpr that projects

pkg/sql/sqlstats/ssmemstorage/ss_mem_iterator.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package ssmemstorage
77

88
import (
9+
"slices"
910
"sort"
1011

1112
"github.com/cockroachdb/cockroach/pkg/sql/appstatspb"
@@ -77,7 +78,7 @@ func (s *StmtStatsIterator) Next() bool {
7778
}
7879

7980
statementStats.mu.Lock()
80-
data := statementStats.mu.data
81+
data := copyDataLocked(statementStats)
8182
distSQLUsed := statementStats.mu.distSQLUsed
8283
vectorized := statementStats.mu.vectorized
8384
fullScan := statementStats.mu.fullScan
@@ -105,6 +106,20 @@ func (s *StmtStatsIterator) Next() bool {
105106
return true
106107
}
107108

109+
// copyDataLocked Copies the statement stat's data object under the mutex.
110+
// This function requires that there is a lock on the stats object.
111+
func copyDataLocked(stats *stmtStats) appstatspb.StatementStatistics {
112+
stats.mu.AssertHeld()
113+
data := stats.mu.data
114+
data.Nodes = slices.Clone(data.Nodes)
115+
data.KVNodeIDs = slices.Clone(data.KVNodeIDs)
116+
data.Regions = slices.Clone(data.Regions)
117+
data.PlanGists = slices.Clone(data.PlanGists)
118+
data.IndexRecommendations = slices.Clone(data.IndexRecommendations)
119+
data.Indexes = slices.Clone(data.Indexes)
120+
return data
121+
}
122+
108123
// Cur returns the appstatspb.CollectedStatementStatistics at the current internal
109124
// counter.
110125
func (s *StmtStatsIterator) Cur() *appstatspb.CollectedStatementStatistics {

0 commit comments

Comments
 (0)