From 19c8ae094d0914226a3fcd75576d39528828dace Mon Sep 17 00:00:00 2001 From: Simon J Mudd Date: Fri, 9 Jan 2015 18:37:44 +0100 Subject: [PATCH] Configure setup_instruments (for the mutex page) if possible on startup, and restore when stopping --- README.md | 8 ++ ..._waits_summary_global_by_event_name_row.go | 5 +- p_s/setup_instruments/setup_instruments.go | 99 +++++++++++++++++++ state/state.go | 14 ++- 4 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 p_s/setup_instruments/setup_instruments.go diff --git a/README.md b/README.md index 097450a..1b4fdc9 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,14 @@ The port if not specified will default to 3306. `pstop` needs `SELECT` access to `performance_schema` tables. It will not run if access to the required tables is not available. +setup_instruments: To view the Mutex page it is likely you will need +to change the configuration of setup_instruments. pstop needs UPDATE +rights on this table to do that. If the pstop user does not have +this right then the configuration will not be modified and you may see +no data. When pstop stops it will restore the setup_instruments +configuration back to its original settings if it successfully +updated the table when starting up. + ### Screens pstop has 5 different screens which get updated by default every second. diff --git a/p_s/events_waits_summary_global_by_event_name/events_waits_summary_global_by_event_name_row.go b/p_s/events_waits_summary_global_by_event_name/events_waits_summary_global_by_event_name_row.go index 86b6bb6..7cbda5e 100644 --- a/p_s/events_waits_summary_global_by_event_name/events_waits_summary_global_by_event_name_row.go +++ b/p_s/events_waits_summary_global_by_event_name/events_waits_summary_global_by_event_name_row.go @@ -42,7 +42,7 @@ func (r *events_waits_summary_global_by_event_name_row) pretty_name() string { } func (r *events_waits_summary_global_by_event_name_row) headings() string { - return fmt.Sprintf("%-30s %10s %6s", "Mutex Name", "Latency", "%") + return fmt.Sprintf("%-30s %10s %6s %6s", "Mutex Name", "Latency", "MtxCnt", "%") } // generate a printable result @@ -52,9 +52,10 @@ func (r *events_waits_summary_global_by_event_name_row) row_content(totals event name = "" } - return fmt.Sprintf("%-30s %10s %6s", + return fmt.Sprintf("%-30s|%10s %6s %6s", name, lib.FormatTime(r.SUM_TIMER_WAIT), + lib.FormatAmount(r.COUNT_STAR), lib.FormatPct(lib.MyDivide(r.SUM_TIMER_WAIT, totals.SUM_TIMER_WAIT))) } diff --git a/p_s/setup_instruments/setup_instruments.go b/p_s/setup_instruments/setup_instruments.go new file mode 100644 index 0000000..c92b6df --- /dev/null +++ b/p_s/setup_instruments/setup_instruments.go @@ -0,0 +1,99 @@ +package setup_instruments + +import ( + "database/sql" + "log" + + "github.com/sjmudd/pstop/lib" +) + +// Error 1142: UPDATE command denied to user +const UPDATE_FAILED = "Error 1142" + +type setup_instruments_row struct { + NAME string + ENABLED string + TIMED string +} + +type SetupInstruments struct { + update_succeeded bool + rows []setup_instruments_row +} + +// Change settings to monitor wait/synch/mutex/% +func (si *SetupInstruments) EnableMutexMonitoring(dbh *sql.DB) { + si.rows = make([]setup_instruments_row, 0, 100) + + // populate the rows which are not set + sql := "SELECT NAME, ENABLED, TIMED FROM setup_instruments WHERE NAME LIKE 'wait/synch/mutex/%' AND ( enabled <> 'YES' OR timed <> 'YES' )" + + lib.Logger.Println("Collecting p_s.setup_instruments wait/synch/mutex configuration settings") + + rows, err := dbh.Query(sql) + if err != nil { + log.Fatal(err) + + + } + defer rows.Close() + + count := 0 + for rows.Next() { + var r setup_instruments_row + if err := rows.Scan( + &r.NAME, + &r.ENABLED, + &r.TIMED); err != nil { + log.Fatal(err) + } + // we collect all information even if it's mainly empty as we may reference it later + si.rows = append(si.rows, r) + count++ + } + if err := rows.Err(); err != nil { + log.Fatal(err) + } + lib.Logger.Println("- found", count, "rows whose configuration need changing") + + // update the rows which need to be set - do multiple updates but I don't care + lib.Logger.Println("Updating p_s.setup_instruments to allow wait/synch/mutex configuration") + + count = 0 + for i := range si.rows { + sql := "UPDATE setup_instruments SET enabled = 'YES', TIMED = 'YES' WHERE NAME = '" + si.rows[i].NAME + "'" + if _, err := dbh.Exec(sql); err == nil { + si.update_succeeded = true + } else { + if err.Error()[0:10] != UPDATE_FAILED { + log.Fatal(err) + } + break + + } + count++ + } + lib.Logger.Println(count, "rows changed in p_s.setup_instruments") +} + +// restore any changed rows back to their original state +func (si *SetupInstruments) Restore(dbh *sql.DB) { + // If the previous update didn't work then don't try to restore + if ! si.update_succeeded { + lib.Logger.Println("Not restoring p_s.setup_instruments to its original settings as previous UPDATE had failed") + return + } else { + lib.Logger.Println("Restoring p_s.setup_instruments to its original settings") + } + + // update the rows which need to be set - do multiple updates but I don't care + count := 0 + for i := range si.rows { + sql := "UPDATE setup_instruments SET enabled = '" + si.rows[i].ENABLED + "', TIMED = '" + si.rows[i].TIMED + "' WHERE NAME = '" + si.rows[i].NAME + "'" + if _, err := dbh.Exec(sql); err != nil { + log.Fatal(err) + } + count++ + } + lib.Logger.Println(count, "rows changed in p_s.setup_instruments") +} diff --git a/state/state.go b/state/state.go index 52fb681..f1fbe88 100644 --- a/state/state.go +++ b/state/state.go @@ -11,14 +11,15 @@ import ( "github.com/sjmudd/pstop/i_s" "github.com/sjmudd/pstop/lib" + ewsgben "github.com/sjmudd/pstop/p_s/events_waits_summary_global_by_event_name" fsbi "github.com/sjmudd/pstop/p_s/file_summary_by_instance" "github.com/sjmudd/pstop/p_s/ps_table" - "github.com/sjmudd/pstop/wait_info" - ewsgben "github.com/sjmudd/pstop/p_s/events_waits_summary_global_by_event_name" + "github.com/sjmudd/pstop/p_s/setup_instruments" tiwsbt "github.com/sjmudd/pstop/p_s/table_io_waits_summary_by_table" tlwsbt "github.com/sjmudd/pstop/p_s/table_lock_waits_summary_by_table" "github.com/sjmudd/pstop/screen" "github.com/sjmudd/pstop/version" + "github.com/sjmudd/pstop/wait_info" ) // what information to show @@ -48,7 +49,8 @@ type State struct { show Show mysql_version string want_relative_stats bool - wait_info.WaitInfo // embedded + wait_info.WaitInfo // embedded + setup_instruments setup_instruments.SetupInstruments } func (state *State) Setup(dbh *sql.DB) { @@ -57,6 +59,7 @@ func (state *State) Setup(dbh *sql.DB) { state.screen.Initialise() + state.setup_instruments.EnableMutexMonitoring(dbh) _, variables := lib.SelectAllGlobalVariablesByVariableName(state.dbh) // setup to their initial types/values state.fsbi = fsbi.NewFileSummaryByInstance(variables) @@ -70,8 +73,8 @@ func (state *State) Setup(dbh *sql.DB) { state.tlwsbt.SetNow() state.tiwsbt.SetWantRelativeStats(state.want_relative_stats) state.tiwsbt.SetNow() - state.users.SetWantRelativeStats(state.want_relative_stats) // ignored - state.users.SetNow() // ignored + state.users.SetWantRelativeStats(state.want_relative_stats) // ignored + state.users.SetNow() // ignored state.ewsgben.SetWantRelativeStats(state.want_relative_stats) // ignored state.ewsgben.SetNow() // ignored @@ -438,6 +441,7 @@ func (state *State) ScreenSetSize(width, height int) { func (state *State) Cleanup() { state.screen.Close() if state.dbh != nil { + state.setup_instruments.Restore(state.dbh) _ = state.dbh.Close() } } -- 2.20.1