Skip to content

Commit

Permalink
Avoid executing status var functions during SHOW STATUS when not re…
Browse files Browse the repository at this point in the history
…quired

Summary:
Status var functions were always executed irrespective of matching
string in the `LIKE` clause of `SHOW STATUS`. This caused execution of
some heavy status var functions like `show_jemalloc_*` every time `SHOW
STATUS` was invoked.

In this change we execute the status var function only for vars whose
names are strict prefixes of the wildcard specified in the `LIKE`
clause. Since we're checking for strict prefix match, we might get false
positives in some cases. We cannot use normal wildcard matching (like
other function-less status vars) because some var names are constructed
recursively in `show_status_array()` (e.g.
`Rpl_semi_sync_master_trx_wait_histogram%` is composed out of
`Rpl_semi_sync_master` and `trx_wait_histogram`).

Reviewed By: midom, anirbanr-fb

Differential Revision: D9561354

fbshipit-source-id: 22f79e0
  • Loading branch information
abhinav04sharma authored and facebook-github-bot committed Nov 1, 2018
1 parent 9f6a63e commit bf0baf3
Showing 1 changed file with 24 additions and 2 deletions.
26 changes: 24 additions & 2 deletions sql/sql_show.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3596,21 +3596,43 @@ static bool show_status_array(THD *thd, const char *wild,
len=name_buffer + sizeof(name_buffer) - prefix_end;
partial_cond= make_cond_for_info_schema(cond, table->pos_in_table_list);

// Find the length of the user's 'LIKE' parameter until the first wildcard
ulonglong before_wild_len= 0;
while (wild &&
wild[before_wild_len] != wild_one &&
wild[before_wild_len] != wild_many &&
wild[before_wild_len] != wild_prefix &&
wild[before_wild_len])
{
++before_wild_len;
}

for (; variables->name; variables++)
{
strnmov(prefix_end, variables->name, len);
name_buffer[sizeof(name_buffer)-1]=0; /* Safety */
if (ucase_names)
make_upper(name_buffer);

const auto len= strlen(name_buffer);
restore_record(table, s->default_values);
table->field[0]->store(name_buffer, strlen(name_buffer),
table->field[0]->store(name_buffer, len,
system_charset_info);

bool prefix_matches= true;
if (variables->type == SHOW_FUNC && before_wild_len > 0)
{
const auto min_len= before_wild_len < len ? before_wild_len : len;
prefix_matches= my_strnncoll(system_charset_info,
(const uchar*) name_buffer, min_len,
(const uchar*) wild, min_len) == 0;
}

/*
if var->type is SHOW_FUNC, call the function.
Repeat as necessary, if new var is again SHOW_FUNC
*/
for (var=variables; var->type == SHOW_FUNC; var= &tmp)
for (var=variables; prefix_matches && var->type == SHOW_FUNC; var= &tmp)
((mysql_show_var_func)(var->value))(thd, &tmp, buff);

SHOW_TYPE show_type=var->type;
Expand Down

0 comments on commit bf0baf3

Please sign in to comment.