diff --git a/server/statistics_handler.go b/server/statistics_handler.go index 4bf7e9c832c4c..24d9e7a202aa7 100644 --- a/server/statistics_handler.go +++ b/server/statistics_handler.go @@ -14,10 +14,10 @@ package server import ( + "errors" "net/http" "time" - "context" "github.com/gorilla/mux" "github.com/pingcap/parser/model" "github.com/pingcap/parser/mysql" @@ -26,9 +26,7 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/gcutil" - "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/sqlexec" - "go.uber.org/zap" ) // StatsHandler is the handler for dumping statistics. @@ -39,17 +37,21 @@ type StatsHandler struct { func (s *Server) newStatsHandler() *StatsHandler { store, ok := s.driver.(*TiDBDriver) if !ok { - logutil.Logger(context.Background()).Error("Illegal driver") + panic("Illegal driver") } do, err := session.GetDomain(store.store) if err != nil { - logutil.Logger(context.Background()).Error("Failed to get domain", zap.Error(err)) + panic("Failed to get domain") } return &StatsHandler{do} } func (sh StatsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + if req.Method != http.MethodGet { + writeError(w, errors.New("only http GET method is supported")) + return + } w.Header().Set("Content-Type", "application/json") params := mux.Vars(req) @@ -88,6 +90,10 @@ func (s *Server) newStatsHistoryHandler() *StatsHistoryHandler { } func (sh StatsHistoryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + if req.Method != http.MethodGet { + writeError(w, errors.New("only http GET method is supported")) + return + } w.Header().Set("Content-Type", "application/json") params := mux.Vars(req) diff --git a/server/statistics_handler_test.go b/server/statistics_handler_test.go index ee5b287778904..965c66332ff45 100644 --- a/server/statistics_handler_test.go +++ b/server/statistics_handler_test.go @@ -31,6 +31,7 @@ import ( "github.com/pingcap/tidb/statistics/handle" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/mockstore/mocktikv" + "github.com/sirupsen/logrus" ) type testDumpStatsSuite struct { @@ -130,6 +131,7 @@ func (ds *testDumpStatsSuite) TestDumpStatsAPI(c *C) { c.Assert(os.Remove(path1), IsNil) }() + logrus.Warning("after snapshot") resp1, err = http.Get("http://127.0.0.1:10090/stats/dump/tidb/test/" + snapshot) c.Assert(err, IsNil) diff --git a/statistics/handle/dump.go b/statistics/handle/dump.go index 0df43a303df39..baae7bf23eeb8 100644 --- a/statistics/handle/dump.go +++ b/statistics/handle/dump.go @@ -25,6 +25,7 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/sqlexec" "github.com/pingcap/tipb/go-tipb" + "github.com/sirupsen/logrus" ) // JSONTable is used for dumping statistics. @@ -85,12 +86,14 @@ func (h *Handle) DumpStatsToJSON(dbName string, tableInfo *model.TableInfo, hist func (h *Handle) tableStatsToJSON(dbName string, tableInfo *model.TableInfo, physicalID int64, historyStatsExec sqlexec.RestrictedSQLExecutor) (*JSONTable, error) { tbl, err := h.tableStatsFromStorage(tableInfo, physicalID, true, historyStatsExec) - if err != nil { - return nil, errors.Trace(err) + if err != nil || tbl == nil { + return nil, err } - if tbl == nil { - return nil, nil + tbl.Version, tbl.ModifyCount, tbl.Count, err = h.statsMetaByTableIDFromStorage(physicalID, historyStatsExec) + if err != nil { + return nil, err } + logrus.Warning("tbl.ModifyCount", tbl.ModifyCount, "tbl.Indices", len(tbl.Indices)) jsonTbl := &JSONTable{ DatabaseName: dbName, TableName: tableInfo.Name.L, diff --git a/statistics/handle/handle.go b/statistics/handle/handle.go index 10d2b0c6ed1b1..a014af2a1c943 100644 --- a/statistics/handle/handle.go +++ b/statistics/handle/handle.go @@ -35,6 +35,7 @@ import ( "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/sqlexec" + "github.com/sirupsen/logrus" atomic2 "go.uber.org/atomic" "go.uber.org/zap" ) @@ -354,6 +355,7 @@ func (h *Handle) indexStatsFromStorage(row chunk.Row, table *statistics.Table, t continue } if idx == nil || idx.LastUpdateVersion < histVer { + logrus.Warning("go into this") hg, err := h.histogramFromStorage(table.PhysicalID, histID, types.NewFieldType(mysql.TypeBlob), distinct, 1, histVer, nullCount, 0, 0, historyStatsExec) if err != nil { return errors.Trace(err) @@ -404,6 +406,7 @@ func (h *Handle) columnStatsFromStorage(row chunk.Row, table *statistics.Table, !isHandle && (col == nil || col.Len() == 0 && col.LastUpdateVersion < histVer) && !loadAll + logrus.Warning("notNeedLoad", notNeedLoad) if notNeedLoad { count, err := h.columnCountFromStorage(table.PhysicalID, histID) if err != nil { @@ -463,7 +466,7 @@ func (h *Handle) tableStatsFromStorage(tableInfo *model.TableInfo, physicalID in table, ok := h.StatsCache.Load().(StatsCache)[physicalID] // If table stats is pseudo, we also need to copy it, since we will use the column stats when // the average error rate of it is small. - if !ok { + if !ok || historyStatsExec != nil { histColl := statistics.HistColl{ PhysicalID: physicalID, HavePhysicalID: true, @@ -673,3 +676,20 @@ func (h *Handle) columnCountFromStorage(tableID, colID int64) (int64, error) { } return rows[0].GetMyDecimal(0).ToInt() } + +func (h *Handle) statsMetaByTableIDFromStorage(tableID int64, historyStatsExec sqlexec.RestrictedSQLExecutor) (version uint64, modifyCount, count int64, err error) { + selSQL := fmt.Sprintf("SELECT version, modify_count, count from mysql.stats_meta where table_id = %d order by version", tableID) + var rows []chunk.Row + if historyStatsExec == nil { + rows, _, err = h.restrictedExec.ExecRestrictedSQL(nil, selSQL) + } else { + rows, _, err = historyStatsExec.ExecRestrictedSQLWithSnapshot(nil, selSQL) + } + if err != nil || len(rows) == 0 { + return + } + version = rows[0].GetUint64(0) + modifyCount = rows[0].GetInt64(1) + count = rows[0].GetInt64(2) + return +}