Skip to content

Commit b65f81f

Browse files
SunRunAwayjackysp
authored andcommitted
distsql: clean the memory usage of MemTracker when a query end… (#10898) (#10971)
1 parent daea7cb commit b65f81f

File tree

3 files changed

+58
-20
lines changed

3 files changed

+58
-20
lines changed

distsql/distsql_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ func (s *testSuite) createSelectNormal(batch, totalRows int, c *C) (*selectResul
4141
SetDesc(false).
4242
SetKeepOrder(false).
4343
SetFromSessionVars(variable.NewSessionVars()).
44+
SetMemTracker(s.sctx, "testSuite.createSelectNormal").
4445
Build()
4546
c.Assert(err, IsNil)
4647

@@ -94,13 +95,29 @@ func (s *testSuite) TestSelectNormal(c *C) {
9495
c.Assert(numAllRows, Equals, 2)
9596
err := response.Close()
9697
c.Assert(err, IsNil)
98+
c.Assert(response.memTracker.BytesConsumed(), Equals, int64(0))
99+
}
100+
101+
func (s *testSuite) TestSelectMemTracker(c *C) {
102+
response, colTypes := s.createSelectNormal(2, 6, c)
103+
response.Fetch(context.TODO())
104+
105+
// Test Next.
106+
chk := chunk.New(colTypes, 3, 3)
107+
err := response.Next(context.TODO(), chk)
108+
c.Assert(err, IsNil)
109+
c.Assert(chk.IsFull(), Equals, true)
110+
err = response.Close()
111+
c.Assert(err, IsNil)
112+
c.Assert(response.memTracker.BytesConsumed(), Equals, int64(0))
97113
}
98114

99115
func (s *testSuite) TestSelectNormalChunkSize(c *C) {
100116
response, colTypes := s.createSelectNormal(100, 1000000, c)
101117
response.Fetch(context.TODO())
102118
s.testChunkSize(response, colTypes, c)
103119
c.Assert(response.Close(), IsNil)
120+
c.Assert(response.memTracker.BytesConsumed(), Equals, int64(0))
104121
}
105122

106123
func (s *testSuite) createSelectStreaming(batch, totalRows int, c *C) (*streamResult, []*types.FieldType) {

distsql/request_builder_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/pingcap/tidb/types"
2727
"github.com/pingcap/tidb/util/codec"
2828
"github.com/pingcap/tidb/util/logutil"
29+
"github.com/pingcap/tidb/util/memory"
2930
"github.com/pingcap/tidb/util/mock"
3031
"github.com/pingcap/tidb/util/ranger"
3132
"github.com/pingcap/tidb/util/testleak"
@@ -49,6 +50,9 @@ type testSuite struct {
4950

5051
func (s *testSuite) SetUpSuite(c *C) {
5152
ctx := mock.NewContext()
53+
ctx.GetSessionVars().StmtCtx = &stmtctx.StatementContext{
54+
MemTracker: memory.NewTracker("testSuite", variable.DefTiDBMemQuotaDistSQL),
55+
}
5256
ctx.Store = &mock.Store{
5357
Client: &mock.Client{
5458
MockResponse: &mockResponse{

distsql/select_result.go

+37-20
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ type selectResult struct {
6666
fieldTypes []*types.FieldType
6767
ctx sessionctx.Context
6868

69-
selectResp *tipb.SelectResponse
70-
respChkIdx int
69+
selectResp *tipb.SelectResponse
70+
selectRespSize int // record the selectResp.Size() when it is initialized.
71+
respChkIdx int
7172

7273
feedback *statistics.QueryFeedback
7374
partialCount int64 // number of partial results.
@@ -94,25 +95,30 @@ func (r *selectResult) fetch(ctx context.Context) {
9495
metrics.DistSQLQueryHistgram.WithLabelValues(r.label, r.sqlType).Observe(duration.Seconds())
9596
}()
9697
for {
98+
var result resultWithErr
9799
resultSubset, err := r.resp.Next(ctx)
98100
if err != nil {
99-
r.results <- resultWithErr{err: errors.Trace(err)}
101+
result.err = err
102+
} else if resultSubset == nil {
103+
// If the result is drained, the resultSubset would be nil
100104
return
101-
}
102-
if resultSubset == nil {
103-
return
104-
}
105-
106-
if r.memTracker != nil {
107-
r.memTracker.Consume(int64(resultSubset.MemSize()))
105+
} else {
106+
result.result = resultSubset
107+
r.memConsume(int64(resultSubset.MemSize()))
108108
}
109109

110110
select {
111-
case r.results <- resultWithErr{result: resultSubset}:
111+
case r.results <- result:
112112
case <-r.closed:
113113
// If selectResult called Close() already, make fetch goroutine exit.
114+
if resultSubset != nil {
115+
r.memConsume(-int64(resultSubset.MemSize()))
116+
}
114117
return
115118
case <-ctx.Done():
119+
if resultSubset != nil {
120+
r.memConsume(-int64(resultSubset.MemSize()))
121+
}
116122
return
117123
}
118124
}
@@ -157,24 +163,21 @@ func (r *selectResult) getSelectResp() error {
157163
if re.err != nil {
158164
return errors.Trace(re.err)
159165
}
160-
if r.memTracker != nil && r.selectResp != nil {
161-
r.memTracker.Consume(-int64(r.selectResp.Size()))
166+
if r.selectResp != nil {
167+
r.memConsume(-int64(r.selectRespSize))
162168
}
163169
if re.result == nil {
164170
r.selectResp = nil
165171
return nil
166172
}
167-
if r.memTracker != nil {
168-
r.memTracker.Consume(-int64(re.result.MemSize()))
169-
}
173+
r.memConsume(-int64(re.result.MemSize()))
170174
r.selectResp = new(tipb.SelectResponse)
171175
err := r.selectResp.Unmarshal(re.result.GetData())
172176
if err != nil {
173177
return errors.Trace(err)
174178
}
175-
if r.memTracker != nil && r.selectResp != nil {
176-
r.memTracker.Consume(int64(r.selectResp.Size()))
177-
}
179+
r.selectRespSize = r.selectResp.Size()
180+
r.memConsume(int64(r.selectRespSize))
178181
if err := r.selectResp.Error; err != nil {
179182
return terror.ClassTiKV.New(terror.ErrCode(err.Code), err.Msg)
180183
}
@@ -207,13 +210,27 @@ func (r *selectResult) readRowsData(chk *chunk.Chunk) (err error) {
207210
return nil
208211
}
209212

213+
func (r *selectResult) memConsume(bytes int64) {
214+
if r.memTracker != nil {
215+
r.memTracker.Consume(bytes)
216+
}
217+
}
218+
210219
// Close closes selectResult.
211220
func (r *selectResult) Close() error {
212-
// Close this channel tell fetch goroutine to exit.
213221
if r.feedback.Actual() >= 0 {
214222
metrics.DistSQLScanKeysHistogram.Observe(float64(r.feedback.Actual()))
215223
}
216224
metrics.DistSQLPartialCountHistogram.Observe(float64(r.partialCount))
225+
// Close this channel to tell the fetch goroutine to exit.
217226
close(r.closed)
227+
for re := range r.results {
228+
if re.result != nil {
229+
r.memConsume(-int64(re.result.MemSize()))
230+
}
231+
}
232+
if r.selectResp != nil {
233+
r.memConsume(-int64(r.selectRespSize))
234+
}
218235
return r.resp.Close()
219236
}

0 commit comments

Comments
 (0)