Skip to content

Commit db621e9

Browse files
committed
*: add a column describing memory usage for table information_schema.processlist (pingcap#10837)
*: add a column describing memory usage for table information_schema.processlist Closes pingcap#10199 Conflicts: executor/show.go infoschema/tables.go infoschema/tables_test.go util/misc_test.go util/processinfo.go
1 parent 6b5b1a6 commit db621e9

13 files changed

+235
-64
lines changed

executor/aggregate_test.go

-5
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,6 @@ func (s *testSuite) TestAggregation(c *C) {
237237
result = tk.MustQuery("SELECT COALESCE ( + 1, cor0.col0 ) + - CAST( NULL AS DECIMAL ) FROM t2, t1 AS cor0, t2 AS cor1 GROUP BY cor0.col1")
238238
result.Check(testkit.Rows("<nil>", "<nil>"))
239239

240-
result = tk.MustQuery("select count(*) from information_schema.columns")
241-
// When adding new memory columns in information_schema, please update this variable.
242-
columnCountOfAllInformationSchemaTables := "793"
243-
result.Check(testkit.Rows(columnCountOfAllInformationSchemaTables))
244-
245240
tk.MustExec("drop table if exists t1")
246241
tk.MustExec("drop table if exists t2")
247242
tk.MustExec("create table t1 (c1 int)")

executor/executor_pkg_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ type testExecSuite struct {
3737

3838
// mockSessionManager is a mocked session manager which is used for test.
3939
type mockSessionManager struct {
40-
PS []util.ProcessInfo
40+
PS []*util.ProcessInfo
4141
}
4242

4343
// ShowProcessList implements the SessionManager.ShowProcessList interface.
44-
func (msm *mockSessionManager) ShowProcessList() map[uint64]util.ProcessInfo {
45-
ret := make(map[uint64]util.ProcessInfo)
44+
func (msm *mockSessionManager) ShowProcessList() map[uint64]*util.ProcessInfo {
45+
ret := make(map[uint64]*util.ProcessInfo)
4646
for _, item := range msm.PS {
4747
ret[item.ID] = item
4848
}
@@ -56,19 +56,19 @@ func (msm *mockSessionManager) Kill(cid uint64, query bool) {
5656

5757
func (s *testExecSuite) TestShowProcessList(c *C) {
5858
// Compose schema.
59-
names := []string{"Id", "User", "Host", "db", "Command", "Time", "State", "Info", "Mem"}
59+
names := []string{"Id", "User", "Host", "db", "Command", "Time", "State", "Info"}
6060
ftypes := []byte{mysql.TypeLonglong, mysql.TypeVarchar, mysql.TypeVarchar,
61-
mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLong, mysql.TypeVarchar, mysql.TypeString, mysql.TypeLonglong}
61+
mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLong, mysql.TypeVarchar, mysql.TypeString}
6262
schema := buildSchema(names, ftypes)
6363

6464
// Compose a mocked session manager.
65-
ps := make([]util.ProcessInfo, 0, 1)
66-
pi := util.ProcessInfo{
65+
ps := make([]*util.ProcessInfo, 0, 1)
66+
pi := &util.ProcessInfo{
6767
ID: 0,
6868
User: "test",
6969
Host: "127.0.0.1",
7070
DB: "test",
71-
Command: "select * from t",
71+
Command: 't',
7272
State: 1,
7373
Info: "",
7474
}

executor/show.go

+2-18
Original file line numberDiff line numberDiff line change
@@ -203,24 +203,8 @@ func (e *ShowExec) fetchShowProcessList() error {
203203

204204
pl := sm.ShowProcessList()
205205
for _, pi := range pl {
206-
var info string
207-
if e.Full {
208-
info = pi.Info
209-
} else {
210-
info = fmt.Sprintf("%.100v", pi.Info)
211-
}
212-
213-
e.appendRow([]interface{}{
214-
pi.ID,
215-
pi.User,
216-
pi.Host,
217-
pi.DB,
218-
pi.Command,
219-
uint64(time.Since(pi.Time) / time.Second),
220-
fmt.Sprintf("%d", pi.State),
221-
info,
222-
pi.Mem,
223-
})
206+
row := pi.ToRowForShow(e.Full)
207+
e.appendRow(row)
224208
}
225209
return nil
226210
}

infoschema/tables.go

+4-15
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,8 @@ var tableProcesslistCols = []columnInfo{
530530
{"COMMAND", mysql.TypeVarchar, 16, mysql.NotNullFlag, "", nil},
531531
{"TIME", mysql.TypeLong, 7, mysql.NotNullFlag, 0, nil},
532532
{"STATE", mysql.TypeVarchar, 7, 0, nil, nil},
533-
{"Info", mysql.TypeString, 512, 0, nil, nil},
533+
{"INFO", mysql.TypeString, 512, 0, nil, nil},
534+
{"MEM", mysql.TypeLonglong, 21, 0, nil, nil},
534535
}
535536

536537
var tableTiDBIndexesCols = []columnInfo{
@@ -626,20 +627,8 @@ func dataForProcesslist(ctx sessionctx.Context) [][]types.Datum {
626627
var records [][]types.Datum
627628
pl := sm.ShowProcessList()
628629
for _, pi := range pl {
629-
var t uint64
630-
if len(pi.Info) != 0 {
631-
t = uint64(time.Since(pi.Time) / time.Second)
632-
}
633-
record := types.MakeDatums(
634-
pi.ID,
635-
pi.User,
636-
pi.Host,
637-
pi.DB,
638-
pi.Command,
639-
t,
640-
fmt.Sprintf("%d", pi.State),
641-
pi.Info,
642-
)
630+
rows := pi.ToRow()
631+
record := types.MakeDatums(rows...)
643632
records = append(records, record)
644633
}
645634
return records

infoschema/tables_test.go

+109
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,18 @@ import (
1717
"fmt"
1818
"os"
1919
"strconv"
20+
"strings"
2021

2122
. "github.com/pingcap/check"
2223
"github.com/pingcap/parser/auth"
24+
"github.com/pingcap/parser/mysql"
25+
"github.com/pingcap/tidb/domain"
2326
"github.com/pingcap/tidb/infoschema"
27+
"github.com/pingcap/tidb/kv"
2428
"github.com/pingcap/tidb/session"
2529
"github.com/pingcap/tidb/statistics"
2630
"github.com/pingcap/tidb/store/mockstore"
31+
"github.com/pingcap/tidb/util"
2732
"github.com/pingcap/tidb/util/testkit"
2833
"github.com/pingcap/tidb/util/testleak"
2934
"github.com/pingcap/tidb/util/testutil"
@@ -87,6 +92,18 @@ func (s *testSuite) TestInfoschemaFieldValue(c *C) {
8792
}, nil, nil), IsTrue)
8893

8994
tk1.MustQuery("select distinct(table_schema) from information_schema.tables").Check(testkit.Rows("INFORMATION_SCHEMA"))
95+
96+
// Fix issue 9836
97+
sm := &mockSessionManager{make(map[uint64]*util.ProcessInfo, 1)}
98+
sm.processInfoMap[1] = &util.ProcessInfo{
99+
ID: 1,
100+
User: "root",
101+
Host: "127.0.0.1",
102+
Command: mysql.ComQuery,
103+
StmtCtx: tk.Se.GetSessionVars().StmtCtx,
104+
}
105+
tk.Se.SetSessionManager(sm)
106+
tk.MustQuery("SELECT user,host,command FROM information_schema.processlist;").Check(testkit.Rows("root 127.0.0.1 Query"))
90107
}
91108

92109
func (s *testSuite) TestDataForTableStatsField(c *C) {
@@ -227,6 +244,98 @@ func (s *testSuite) TestCharacterSetCollations(c *C) {
227244
tk.MustExec("DROP DATABASE charset_collate_test")
228245
}
229246

247+
var _ = Suite(&testTableSuite{})
248+
249+
type testTableSuite struct {
250+
store kv.Storage
251+
dom *domain.Domain
252+
}
253+
254+
func (s *testTableSuite) SetUpSuite(c *C) {
255+
testleak.BeforeTest()
256+
257+
var err error
258+
s.store, err = mockstore.NewMockTikvStore()
259+
c.Assert(err, IsNil)
260+
session.SetStatsLease(0)
261+
s.dom, err = session.BootstrapSession(s.store)
262+
c.Assert(err, IsNil)
263+
}
264+
265+
func (s *testTableSuite) TearDownSuite(c *C) {
266+
defer testleak.AfterTest(c)()
267+
s.dom.Close()
268+
s.store.Close()
269+
}
270+
271+
type mockSessionManager struct {
272+
processInfoMap map[uint64]*util.ProcessInfo
273+
}
274+
275+
func (sm *mockSessionManager) ShowProcessList() map[uint64]*util.ProcessInfo { return sm.processInfoMap }
276+
277+
func (sm *mockSessionManager) GetProcessInfo(id uint64) (*util.ProcessInfo, bool) {
278+
rs, ok := sm.processInfoMap[id]
279+
return rs, ok
280+
}
281+
282+
func (sm *mockSessionManager) Kill(connectionID uint64, query bool) {}
283+
284+
func (s *testTableSuite) TestSomeTables(c *C) {
285+
tk := testkit.NewTestKit(c, s.store)
286+
287+
tk.MustQuery("select * from information_schema.COLLATION_CHARACTER_SET_APPLICABILITY where COLLATION_NAME='utf8mb4_bin';").Check(
288+
testkit.Rows("utf8mb4_bin utf8mb4"))
289+
tk.MustQuery("select * from information_schema.SESSION_VARIABLES where VARIABLE_NAME='tidb_retry_limit';").Check(testkit.Rows("tidb_retry_limit 10"))
290+
// cherry-pick https://github.com/pingcap/tidb/pull/7831
291+
//tk.MustQuery("select * from information_schema.ENGINES;").Check(testkit.Rows("InnoDB DEFAULT Supports transactions, row-level locking, and foreign keys YES YES YES"))
292+
tk.MustQuery("select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME='gc_delete_range';").Check(testkit.Rows("def mysql delete_range_index mysql gc_delete_range UNIQUE"))
293+
tk.MustQuery("select * from information_schema.KEY_COLUMN_USAGE where TABLE_NAME='stats_meta' and COLUMN_NAME='table_id';").Check(
294+
testkit.Rows("def mysql tbl def mysql stats_meta table_id 1 <nil> <nil> <nil> <nil>"))
295+
// https://github.com/pingcap/tidb/pull/9898
296+
//tk.MustQuery("select * from information_schema.STATISTICS where TABLE_NAME='columns_priv' and COLUMN_NAME='Host';").Check(
297+
// testkit.Rows("def mysql columns_priv 0 mysql PRIMARY 1 Host A <nil> <nil> <nil> BTREE "))
298+
tk.MustQuery("select * from information_schema.USER_PRIVILEGES where PRIVILEGE_TYPE='Select';").Check(testkit.Rows("'root'@'%' def Select YES"))
299+
300+
sm := &mockSessionManager{make(map[uint64]*util.ProcessInfo, 2)}
301+
sm.processInfoMap[1] = &util.ProcessInfo{
302+
ID: 1,
303+
User: "user-1",
304+
Host: "localhost",
305+
DB: "information_schema",
306+
Command: byte(1),
307+
State: 1,
308+
Info: "do something",
309+
StmtCtx: tk.Se.GetSessionVars().StmtCtx,
310+
}
311+
sm.processInfoMap[2] = &util.ProcessInfo{
312+
ID: 2,
313+
User: "user-2",
314+
Host: "localhost",
315+
DB: "test",
316+
Command: byte(2),
317+
State: 2,
318+
Info: strings.Repeat("x", 101),
319+
StmtCtx: tk.Se.GetSessionVars().StmtCtx,
320+
}
321+
tk.Se.SetSessionManager(sm)
322+
tk.MustQuery("select * from information_schema.PROCESSLIST order by ID;").Sort().Check(
323+
testkit.Rows(
324+
fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 1 %s 0", "do something"),
325+
fmt.Sprintf("2 user-2 localhost test Init DB 9223372036 2 %s 0", strings.Repeat("x", 101)),
326+
))
327+
tk.MustQuery("SHOW PROCESSLIST;").Sort().Check(
328+
testkit.Rows(
329+
fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 1 %s", "do something"),
330+
fmt.Sprintf("2 user-2 localhost test Init DB 9223372036 2 %s", strings.Repeat("x", 100)),
331+
))
332+
tk.MustQuery("SHOW FULL PROCESSLIST;").Sort().Check(
333+
testkit.Rows(
334+
fmt.Sprintf("1 user-1 localhost information_schema Quit 9223372036 1 %s", "do something"),
335+
fmt.Sprintf("2 user-2 localhost test Init DB 9223372036 2 %s", strings.Repeat("x", 101)),
336+
))
337+
}
338+
230339
func (s *testSuite) TestSchemataCharacterSet(c *C) {
231340
testleak.BeforeTest()
232341
defer testleak.AfterTest(c)()

planner/core/logical_plans.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ type LogicalUnionScan struct {
312312
conditions []expression.Expression
313313
}
314314

315-
// DataSource represents a tablescan without condition push down.
315+
// DataSource represents a tableScan without condition push down.
316316
type DataSource struct {
317317
logicalSchemaProducer
318318

planner/core/planbuilder.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1873,9 +1873,9 @@ func buildShowSchema(s *ast.ShowStmt) (schema *expression.Schema) {
18731873
mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar,
18741874
}
18751875
case ast.ShowProcessList:
1876-
names = []string{"Id", "User", "Host", "db", "Command", "Time", "State", "Info", "Mem"}
1876+
names = []string{"Id", "User", "Host", "db", "Command", "Time", "State", "Info"}
18771877
ftypes = []byte{mysql.TypeLonglong, mysql.TypeVarchar, mysql.TypeVarchar,
1878-
mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLong, mysql.TypeVarchar, mysql.TypeString, mysql.TypeLonglong}
1878+
mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLong, mysql.TypeVarchar, mysql.TypeString}
18791879
case ast.ShowPumpStatus:
18801880
names = []string{"NodeID", "Address", "State", "Max_Commit_Ts", "Update_Time"}
18811881
ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong, mysql.TypeVarchar}

server/driver.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ type QueryCtx interface {
8484
Auth(user *auth.UserIdentity, auth []byte, salt []byte) bool
8585

8686
// ShowProcess shows the information about the session.
87-
ShowProcess() util.ProcessInfo
87+
ShowProcess() *util.ProcessInfo
8888

8989
// GetSessionVars return SessionVars.
9090
GetSessionVars() *variable.SessionVars

server/driver_tidb.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ func (tc *TiDBContext) Prepare(sql string) (statement PreparedStatement, columns
332332
}
333333

334334
// ShowProcess implements QueryCtx ShowProcess method.
335-
func (tc *TiDBContext) ShowProcess() util.ProcessInfo {
335+
func (tc *TiDBContext) ShowProcess() *util.ProcessInfo {
336336
return tc.session.ShowProcess()
337337
}
338338

server/server.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -429,9 +429,9 @@ func (cc *clientConn) connectInfo() *variable.ConnectionInfo {
429429
}
430430

431431
// ShowProcessList implements the SessionManager interface.
432-
func (s *Server) ShowProcessList() map[uint64]util.ProcessInfo {
432+
func (s *Server) ShowProcessList() map[uint64]*util.ProcessInfo {
433433
s.rwlock.RLock()
434-
rs := make(map[uint64]util.ProcessInfo, len(s.clients))
434+
rs := make(map[uint64]*util.ProcessInfo, len(s.clients))
435435
for _, client := range s.clients {
436436
if atomic.LoadInt32(&client.status) == connStatusWaitShutdown {
437437
continue

session/session.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ import (
6565
"golang.org/x/net/context"
6666
)
6767

68-
// Session context
68+
// Session context, it is consistent with the lifecycle of a client connection.
6969
type Session interface {
7070
sessionctx.Context
7171
Status() uint16 // Flag of current status, such as autocommit.
@@ -89,7 +89,7 @@ type Session interface {
8989
SetSessionManager(util.SessionManager)
9090
Close()
9191
Auth(user *auth.UserIdentity, auth []byte, salt []byte) bool
92-
ShowProcess() util.ProcessInfo
92+
ShowProcess() *util.ProcessInfo
9393
// PrePareTxnCtx is exported for test.
9494
PrepareTxnCtx(context.Context)
9595
// FieldList returns fields list of a table.
@@ -787,16 +787,17 @@ func (s *session) SetProcessInfo(sql string, t time.Time, command byte) {
787787
pi := util.ProcessInfo{
788788
ID: s.sessionVars.ConnectionID,
789789
DB: s.sessionVars.CurrentDB,
790-
Command: mysql.Command2Str[command],
790+
Command: command,
791791
Time: t,
792792
State: s.Status(),
793793
Info: sql,
794+
StmtCtx: s.sessionVars.StmtCtx,
794795
}
795796
if s.sessionVars.User != nil {
796797
pi.User = s.sessionVars.User.Username
797798
pi.Host = s.sessionVars.User.Hostname
798799
}
799-
s.processInfo.Store(pi)
800+
s.processInfo.Store(&pi)
800801
}
801802

802803
func (s *session) executeStatement(ctx context.Context, connID uint64, stmtNode ast.StmtNode, stmt sqlexec.Statement, recordSets []sqlexec.RecordSet) ([]sqlexec.RecordSet, error) {
@@ -1528,12 +1529,11 @@ func (s *session) GetStore() kv.Storage {
15281529
return s.store
15291530
}
15301531

1531-
func (s *session) ShowProcess() util.ProcessInfo {
1532-
var pi util.ProcessInfo
1532+
func (s *session) ShowProcess() *util.ProcessInfo {
1533+
var pi *util.ProcessInfo
15331534
tmp := s.processInfo.Load()
15341535
if tmp != nil {
1535-
pi = tmp.(util.ProcessInfo)
1536-
pi.Mem = s.GetSessionVars().StmtCtx.MemTracker.BytesConsumed()
1536+
pi = tmp.(*util.ProcessInfo)
15371537
}
15381538
return pi
15391539
}

0 commit comments

Comments
 (0)