Mysql命令show global status求根溯源

近来,发现好多公司对mysql的性能监控是通过show global status实现的,因此对于这个命令想要探究一番,看他是否是实时更新的。

在此之前,我们必须搞明白mysql对于这个命令的执行过程来确认它所显示的数据究竟是什么、是否实时更新以及是否准确。借这个机会,我们也可以了解客户端与mysql服务器是如何交互的以及对于SQL命令的一般执行过程。为此,我觉得这是一个很好的契机,当然中间也参考了好多人对于以前SQL版本的见解。

鉴于SQL命令的一般执行过程比较复杂,我仅仅叙述一个大概,虽然不是很准确,但是由于由源码和gdb调试的结果做参考,为此应该是基本正确。

注意:我们的mysql版本是mysql5.7.13,运行环境是Linux,仅对于show global status的过程进行解析。

一、show global status的具体流程

1.mysql客户端的相关动作

Mysql命令show global status求根溯源

Mysql命令show global status求根溯源

read_and_execute和main在mysql.cc中

read_and_execute正如其名完成mysql对命令的读入和执行,方式分为批量读入和不成批量的读入,对于show global status是后者

(1)readline函数完成对单行命令的读入。

(2)find_command函数对命令语法进行检查。

(3)com_go函数对命令执行发送、接收结果以及显示

  1)mysql_real_query_for_lazy函数对命令执行发送。

  2)mysql_next_result函数和mysql_store_result_for_lazy函数完成对结果的接收。

  3)print_table_data*以及print_tab_data函数对结果按要求的格式进行打印。

2.mysql服务端的相关动作。

mysql服务端在建立连接后会为每一个连接创建一个独立线程去处理该连接所发送的请求。(处理流程如图0所示)

Mysql命令show global status求根溯源

                                 图0.mysql服务端处理流程

Mysql命令show global status求根溯源

              图1、解析sql的逻辑

(1)在handle_connection中(图1的#5)

关闭连接并减少连接数

     close_connection(thd, , false, false);

     thd->get_stmt_da()->reset_diagnostics_area();
thd->release_resources(); // Clean up errors now, before possibly waiting for a new connection.
ERR_remove_state(); thd_manager->remove_thd(thd);
Connection_handler_manager::dec_connection_count();

这是handle_connection函数的核心

     if (thd_prepare_connection(thd))
handler_manager->inc_aborted_connects();
else
{
while (thd_connection_alive(thd))
{
mysql_audit_release(thd);
if (do_command(thd))
break;
}
end_connection(thd);
}
close_connection(thd, , false, false);

处理命令的入口在do_command中

我们可以看到它处理的逻辑是只要这个连接还持续着,它就会连续执行命令。

(2)在do_command函数中(图1的#4)

 if (classic)
{
/*
This thread will do a blocking read from the client which
will be interrupted when the next command is received from
the client, the connection is closed or "net_wait_timeout"
number of seconds has passed.
*/
net= thd->get_protocol_classic()->get_net();
my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
net_new_transaction(net);
}
   thd->m_server_idle= true;
rc= thd->get_protocol()->get_command(&com_data, &command);
thd->m_server_idle= false;

通过这个获取命令的类型command和命令的内容com_data

在进行一些准备过程后

  return_value= dispatch_command(thd, &com_data, command);

进入函数dispatch_command

(3)在函数dispatch_command中(图1的#3)

  thd->set_command(command);
/*
Commands which always take a long time are logged into
the slow log only if opt_log_slow_admin_statements is set.
*/
thd->enable_slow_log= TRUE;
thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
thd->set_time();

在这里设置了命令给thd,并设置了开始时间

   if (!(server_command_flags[command] & CF_SKIP_QUESTIONS))
thd->status_var.questions++;

这里统计了请求数的数量。

由于我们的请求类型是COM_QUERY为此进入了COM_QUERY分支

  case COM_QUERY:
{
DBUG_ASSERT(thd->m_digest == NULL);
thd->m_digest= & thd->m_digest_state;
thd->m_digest->reset(thd->m_token_array, max_digest_length); if (alloc_query(thd, com_data->com_query.query,
com_data->com_query.length))
break; // fatal error is set
MYSQL_QUERY_START(const_cast<char*>(thd->query().str), thd->thread_id(),
(char *) (thd->db().str ? thd->db().str : ""),
(char *) thd->security_context()->priv_user().str,
(char *) thd->security_context()->host_or_ip().str); const char *packet_end= thd->query().str + thd->query().length; if (opt_general_log_raw)
query_logger.general_log_write(thd, command, thd->query().str,
thd->query().length); DBUG_PRINT("query",("%-.4096s", thd->query().str)); #if defined(ENABLED_PROFILING)
thd->profiling.set_query_source(thd->query().str, thd->query().length);
#endif MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query().str,
thd->query().length); Parser_state parser_state;
if (parser_state.init(thd, thd->query().str, thd->query().length))
break; mysql_parse(thd, &parser_state);

general_log_write会写一个general query log,但是由于我们记录了binlog,为此该选项为false

同时进入主要的处理流程mysql_parse

(4)在mysql_parse函数中(图1的#2)

该函数主要进行了两个主要流程:parse_sql函数和mysql_execute_command函数。

1)parse_sql函数主要是为了完成解析sql命令,将一些sql命令进行转换,建立sql命令的依赖关系,从而完成执行顺序的构建。

2)mysql_execute_command函数主要根据命令类型执行命令。

(5)在parse_sql函数中(图1的#1)

在此函数中最主要执行的函数是MYSQLparse(thd),会递归执行该函数多次,具体流程和解析过程有关,MYSQLparse(thd)就是yyparse

(6)在yyparse函数中(图1的#0)

在解析show global status时主要执行了以下代码,该代码是在sql_parse.yy上执行的,这是一个开源的GUN bison语法分析器的格式

由于过于复杂,所以我取了主要的部分,供大家参考

1)初始化创建信息

Mysql命令show global status求根溯源

2)设置语句属性

Mysql命令show global status求根溯源

3)将语句进行转化

Mysql命令show global status求根溯源

通过bulid_show_global_status将语句转化成SELECT * FROM

(SELECT VARIABLE_NAME as Variable_name, VARIABLE_VALUE as Value

                 FROM performance_schema.global_status) global_status

Mysql命令show global status求根溯源

4)将其设置为singlequery

Mysql命令show global status求根溯源Mysql命令show global status求根溯源

        图2       执行SQL命令的逻辑关系(初始化数据)

(7)在mysql_execute_command函数(图2#16)中

由于本语句的类型是SQLCOM_SHOW_STATUS,为此进入

 case SQLCOM_SHOW_STATUS:
{
system_status_var old_status_var= thd->status_var;
thd->initial_status_var= &old_status_var; if (!(res= select_precheck(thd, lex, all_tables, first_table)))
res= execute_sqlcom_select(thd, all_tables); /* Don't log SHOW STATUS commands to slow query log */
thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
SERVER_QUERY_NO_GOOD_INDEX_USED);
/*
restore status variables, as we don't want 'show status' to cause
changes
*/
mysql_mutex_lock(&LOCK_status);
add_diff_to_status(&global_status_var, &thd->status_var,
&old_status_var);
thd->status_var= old_status_var;
thd->initial_status_var= NULL;
mysql_mutex_unlock(&LOCK_status);
break;
}

(8)在execute_sqlcom_select函数(图2#15)中

会根据进行一些限制以及设置定时器

 {
SELECT_LEX *param= lex->unit->global_parameters();
if (!param->explicit_limit)
param->select_limit=
new Item_int((ulonglong) thd->variables.select_limit);
} //check if timer is applicable to statement, if applicable then set timer.
if (is_timer_applicable_to_statement(thd))
statement_timer_armed= set_statement_timer(thd);

由于命令没有扩展同时能打开所有表,进入handle_query

 if (!(res= open_tables_for_query(thd, all_tables, )))
{
MYSQL_SELECT_START(const_cast<char*>(thd->query().str));
if (lex->is_explain())
{
/*
We always use Query_result_send for EXPLAIN, even if it's an EXPLAIN
for SELECT ... INTO OUTFILE: a user application should be able
to prepend EXPLAIN to any query and receive output for it,
even if the query itself redirects the output.
*/
Query_result *const result= new Query_result_send;
if (!result)
return true; /* purecov: inspected */
res= handle_query(thd, lex, result, , );
}
else
{
Query_result *result= lex->result;
if (!result && !(result= new Query_result_send()))
return true; /* purecov: inspected */
Query_result *save_result= result;
Query_result *analyse_result= NULL;
if (lex->proc_analyse)
{
if ((result= analyse_result=
new Query_result_analyse(result, lex->proc_analyse)) == NULL)
return true;
}
res= handle_query(thd, lex, result, , );
delete analyse_result;
if (save_result != lex->result)
delete save_result;
}

(9)在handle_query函数(图2#14)中

该函数分成连个主要流程optimize和exec

1)optimize先进行sql命令执行方式的优化,再建立了sql命令的执行计划,结合资料发现它会优化where条件、having条件、group by、sort、limit以及jion等语句的执行计划,不会对本命令产生太大的影响,做出此判断的理由是我的where条件事实上是NULL。(详情见(6)的3)),为此不做具体分析。

2)exec先按计划执行命令,再将结果反馈给用户。(这步是本次的主要流程)

   if (single_query)
{
unit->set_limit(unit->global_parameters()); select->context.resolve_in_select_list= true;
select->set_query_result(result);
select->make_active_options(added_options, removed_options);
select->fields_list= select->item_list; if (select->prepare(thd))
goto err; unit->set_prepared();
}
   if (single_query)
{
if (select->optimize(thd))
goto err; unit->set_optimized();
}
else
{
if (unit->optimize(thd))
goto err;
} if (lex->is_explain())
{
if (explain_query(thd, unit))
goto err; /* purecov: inspected */
}
else
{
if (single_query)
{
select->join->exec();
unit->set_executed();
if (thd->is_error())
goto err;
}
else
{
if (unit->execute(thd))
goto err;
}
}

(10)在exec函数(图2#13 #7)中

为了说明,方便这边将发送的数据结构做一个交代。

   query_result->send_result_set_metadata(*fields,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);

这是一个Item的链表

接着我们找到Item的定义,发现其有以下定义:

   /*
str_values's main purpose is to be used to cache the value in
save_in_field
*/
String str_value; Item_name_string item_name; /* Name from select */
Item_name_string orig_name; /* Original item name (if it was renamed)*/

我们发现他的所有数值都是以字符串形式存在的。

该函数会执行do_select来完成对语句的查询工作。

(11)在do_select函数(图2#12,#6)中

由于需要临时表,为此他进入

   else
{
QEP_TAB *qep_tab= join->qep_tab + join->const_tables;
DBUG_ASSERT(join->primary_tables);
error= join->first_select(join,qep_tab,);
if (error >= NESTED_LOOP_OK)
error= join->first_select(join,qep_tab,);
}

first_select指向sub_select

当不需要临时表时,他使用get_end_select_func即end_send()

 if (join->plan_is_const() && !join->need_tmp)
{
Next_select_func end_select= join->get_end_select_func();

(12)在sub_select函数(图2#11,#5)中

sub_select首先扫描之前的依赖表(prepare_scan),然后如果该表不依赖其他表,则进入批量处理performance schema的过程

  while (rc == NESTED_LOOP_OK && join->return_tab >= qep_tab_idx)
{
int error;
if (in_first_read)
{
in_first_read= false;
error= (*qep_tab->read_first_record)(qep_tab);
}
else
error= info->read_record(info); DBUG_EXECUTE_IF("bug13822652_1", join->thd->killed= THD::KILL_QUERY;); if (error > || (join->thd->is_error())) // Fatal error
rc= NESTED_LOOP_ERROR;
else if (error < )
break;
else if (join->thd->killed) // Aborted by user
{
join->thd->send_kill_message();
rc= NESTED_LOOP_KILLED;
}
else
{
if (qep_tab->keep_current_rowid)
qep_tab->table()->file->position(qep_tab->table()->record[]);
rc= evaluate_join_record(join, qep_tab);
}
} if (rc == NESTED_LOOP_OK &&
qep_tab->last_inner() != NO_PLAN_IDX &&
!qep_tab->found)
rc= evaluate_null_complemented_join_record(join, qep_tab); if (pfs_batch_update)
qep_tab->table()->file->end_psi_batch_mode();

read_first_record初始化数据(在一次循环里只执行1次),read_record会读取下一条数据

sql\sql_executor.cc:2819:read_first_record =  join_init_read_record;

              read_record= rr_sequential;

(13)在prepare_scan函数(图2#10)中

 bool QEP_TAB::prepare_scan()
{
// Check whether materialization is required.
if (!materialize_table || materialized)
return false; // Materialize table prior to reading it
if ((*materialize_table)(this))
return true; materialized= true; // Bind to the rowid buffer managed by the TABLE object.
if (copy_current_rowid)
copy_current_rowid->bind_buffer(table()->file->ref); return false;
}

sql\sql_select.cc: 2302:materialize_table =  join_materialize_derived;

(14)在join_materialize_derived函数(图2#9)中

 int join_materialize_derived(QEP_TAB *tab)
{
THD *const thd= tab->table()->in_use;
TABLE_LIST *const derived= tab->table_ref; DBUG_ASSERT(derived->uses_materialization() && !tab->materialized); if (derived->materializable_is_const()) // Has been materialized by optimizer
return NESTED_LOOP_OK; bool res= derived->materialize_derived(thd);
res|= derived->cleanup_derived();
DEBUG_SYNC(thd, "after_materialize_derived");
return res ? NESTED_LOOP_ERROR : NESTED_LOOP_OK;
}

(13在materialize_derived(图2#8)中

由于不是union重新进入exec(详细见(10))

   if (unit->is_union())
{
// execute union without clean up
res= unit->execute(thd);
}
else
{
SELECT_LEX *first_select= unit->first_select();
JOIN *join= first_select->join;
SELECT_LEX *save_current_select= thd->lex->current_select();
thd->lex->set_current_select(first_select); DBUG_ASSERT(join && join->is_optimized()); unit->set_limit(first_select); join->exec();
res= join->error;
thd->lex->set_current_select(save_current_select);
}

(14)在join_init_read_record(图2#4)中

 /**
@brief Prepare table for reading rows and read first record.
@details
Prior to reading the table following tasks are done, (in the order of
execution):
.) derived tables are materialized
.) duplicates removed (tmp tables only)
.) table is sorted with filesort (both non-tmp and tmp tables)
After this have been done this function resets quick select, if it's
present, sets up table reading functions, and reads first record. @retval
0 Ok
@retval
-1 End of records
@retval
1 Error
*/ int join_init_read_record(QEP_TAB *tab)
{
int error; if (tab->distinct && tab->remove_duplicates()) // Remove duplicates.
return ;
if (tab->filesort && tab->sort_table()) // Sort table.
return ; if (tab->quick() && (error= tab->quick()->reset()))
{
/* Ensures error status is propageted back to client */
report_handler_error(tab->table(), error);
return ;
}
if (init_read_record(&tab->read_record, tab->join()->thd, NULL, tab,
, , FALSE))
return ; return (*tab->read_record.read_record)(&tab->read_record);
}

进入init_read_record

(15)在init_read_record(图2#3)中

不进行quick操作即不进行range,也不进行sort

   else
{
DBUG_PRINT("info",("using rr_sequential"));
info->read_record=rr_sequential;
if ((error= table->file->ha_rnd_init()))
goto err;
/* We can use record cache if we don't update dynamic length tables */
if (!table->no_cache &&
(use_record_cache > ||
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) ||
(use_record_cache < &&
!(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE))))
(void) table->file->extra_opt(HA_EXTRA_CACHE,
thd->variables.read_buff_size);
}

在其中调用ha_rnd_init函数,下一个if几乎不进入

(16)在ha_rnd_init(图2#2)中

调用了rnd_init,他是一个虚方法,会触发调用ha_perfschema::rnd_init

(17)在ha_perfschema::rnd_init(图2#1)中

 int ha_perfschema::rnd_init(bool scan)
{
int result;
DBUG_ENTER("ha_perfschema::rnd_init"); DBUG_ASSERT(m_table_share);
DBUG_ASSERT(m_table_share->m_open_table != NULL); stats.records= ;
if (m_table == NULL)
m_table= m_table_share->m_open_table();
else
m_table->reset_position(); if (m_table != NULL)
m_table->rnd_init(scan); result= m_table ? : HA_ERR_OUT_OF_MEM;
DBUG_RETURN(result);
}

(18)在ha_perfschema::rnd_init(图2#0)中

 int table_global_status::rnd_init(bool scan)
{
/* Build a cache of all global status variables. Sum across threads. */
m_status_cache.materialize_global(); /* Record the current number of status variables to detect subsequent changes. */
ulonglong status_version= m_status_cache.get_status_array_version(); /*
The table context holds the current version of the global status array.
If scan == true, then allocate a new context from mem_root and store in TLS.
If scan == false, then restore from TLS.
*/
m_context= (table_global_status_context *)current_thd->alloc(sizeof(table_global_status_context));
new(m_context) table_global_status_context(status_version, !scan);
return ;
}

在materialize_global中

 template <class Var_type>
int PFS_variable_cache<Var_type>::materialize_global()
{
if (is_materialized())
return ; return do_materialize_global();
}

执行do_materialize_global

   PFS_connection_status_visitor visitor(&status_totals);
PFS_connection_iterator::visit_global(false, /* hosts */
false, /* users */
false, /* accounts */
false, /* threads */
true, /* THDs */
&visitor);

(19)在PFS_status_variable_cache::init_show_var_array中

函数将all_status_vars里符合要求的赋给m_show_var_array中m_show_var_array的类型详见(这一节的(21)),至于all_status_vars的来源,我会在后面第二章第1小节中会提到。

   for (Status_var_array::iterator show_var_iter= all_status_vars.begin();
show_var_iter != all_status_vars.end();
show_var_iter++)
{
SHOW_VAR show_var= *show_var_iter; /* Check if this status var should be excluded from the query. */
if (filter_show_var(&show_var, strict))
continue; if (show_var.type == SHOW_ARRAY)
{
/* Expand nested subarray. The name is used as a prefix. */
expand_show_var_array((SHOW_VAR *)show_var.value, show_var.name, strict);
}
else
{
show_var.name= make_show_var_name(NULL, show_var.name);
m_show_var_array.push_back(show_var);
}
}

至于为什么用转化的sql语句只能得到206个,而转化后能得到353个,少了Com开头的项目,后面的第二章第2小节中会提到,正好少147个。

 bool PFS_status_variable_cache::filter_by_name(const SHOW_VAR *show_var)
{
DBUG_ASSERT(show_var);
DBUG_ASSERT(show_var->name); if (show_var->type == SHOW_ARRAY)
{
/* The SHOW_ARRAY name is the prefix for the variables in the subarray. */
const char *prefix= show_var->name;
/* Exclude COM counters if not a SHOW STATUS command. */
if (!my_strcasecmp(system_charset_info, prefix, "Com") && !m_show_command)
return true;
}
else
{
/*
Slave status resides in Performance Schema replication tables. Exclude
these slave status variables from the SHOW STATUS command and from the
status tables.
Assume null prefix to ensure that only server-defined slave status
variables are filtered.
*/
const char *name= show_var->name;
if (!my_strcasecmp(system_charset_info, name, "Slave_running") ||
!my_strcasecmp(system_charset_info, name, "Slave_retried_transactions") ||
!my_strcasecmp(system_charset_info, name, "Slave_last_heartbeat") ||
!my_strcasecmp(system_charset_info, name, "Slave_received_heartbeats") ||
!my_strcasecmp(system_charset_info, name, "Slave_heartbeat_period"))
{
return true;
}
} return false;
}

秘密在PFS_status_variable_cache::filter_show_var中的filter_by_name中

(20)在FS_connection_iterator::visit_global中

m_status_vars指向do_materialize_global对应于status_totals

对于global_status_var的值进行统计PFS_connection_status_visitor::visit_global()->add_to_status(m_status_vars, &global_status_var, false);将global_status_var加到m_status_vars里。
对于每个线程对应status_var的值进行统计Global_THD_manager::do_for_all_thd() -> for_each()->add_to_status(m_status_vars, &thd->status_var, false);将global_status_var加到m_status_vars里。

对于global_status_var的类型感兴趣的话在第二章第3小节中我会提到。

 manifest(m_current_thd, m_show_var_array.begin(), &status_totals, "", false, true);

(21)在PFS_status_variable_cache::manifest中

对于SHOW_VAR

 /**
SHOW STATUS Server status variable
*/
struct st_mysql_show_var
{
const char *name;
char *value;
enum enum_mysql_show_type type;
enum enum_mysql_show_scope scope;
};

对于enum_mysql_show_type的定义,显示的类型,即是函数、数组、字符、字符串等等。

 /**
Declarations for SHOW STATUS support in plugins
*/
enum enum_mysql_show_type
{
SHOW_UNDEF, SHOW_BOOL,
SHOW_INT, ///< shown as _unsigned_ int
SHOW_LONG, ///< shown as _unsigned_ long
SHOW_LONGLONG, ///< shown as _unsigned_ longlong
SHOW_CHAR, SHOW_CHAR_PTR,
SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE
#ifdef MYSQL_SERVER
/*
This include defines server-only values of the enum.
Using them in plugins is not supported.
*/
#include "sql_plugin_enum.h"
#endif
};

对于enum_mysql_show_scope的定义,显示用于那种命令。

 /**
Status variable scope.
Only GLOBAL status variable scope is available in plugins.
*/
enum enum_mysql_show_scope
{
SHOW_SCOPE_UNDEF,
SHOW_SCOPE_GLOBAL
#ifdef MYSQL_SERVER
/* Server-only values. Not supported in plugins. */
,
SHOW_SCOPE_SESSION,
SHOW_SCOPE_ALL
#endif
};

对于每个m_show_var_array中的元素

首先执行SHOW_VAR下表示类型是函数的函数

     /*
If the value is a function reference, then execute the function and
reevaluate the new SHOW_TYPE and value. Handle nested case where
SHOW_FUNC resolves to another SHOW_FUNC.
*/
if (show_var_ptr->type == SHOW_FUNC)
{
show_var_tmp= *show_var_ptr;
/*
Execute the function reference in show_var_tmp->value, which returns
show_var_tmp with a new type and new value.
*/
for (const SHOW_VAR *var= show_var_ptr; var->type == SHOW_FUNC; var= &show_var_tmp)
{
((mysql_show_var_func)(var->value))(thd, &show_var_tmp, value_buf);
}
show_var_ptr= &show_var_tmp;
}

再如果遇到SHOW_VAR下表示类型是数组的,就再次调用manifest展开数组,方便赋值。

  if (show_var_ptr->type == SHOW_ARRAY)
{
/*
Status variables of type SHOW_ARRAY were expanded and filtered by
init_show_var_array(), except where a SHOW_FUNC resolves into a
SHOW_ARRAY, such as with InnoDB. Recurse to expand the subarray.
*/
manifest(thd, (SHOW_VAR *)show_var_ptr->value, status_vars, show_var_ptr->name, true, strict);
}

最后遇到SHOW_VAR下表示类型不是数组的,将m_show_var_array复制给了m_cache。

 else
{
/* Add the materialized status variable to the cache. */
SHOW_VAR show_var= *show_var_ptr;
/*
For nested array expansions, make a copy of the variable name, just as
done in init_show_var_array().
*/
if (nested_array)
show_var.name= make_show_var_name(prefix, show_var_ptr->name); /* Convert status value to string format. Add to the cache. */
Status_variable status_var(&show_var, status_vars, m_query_scope);
m_cache.push_back(status_var);
}

Mysql命令show global status求根溯源

               图3       执行SQL命令的逻辑关系(读取下一条数据)

(22)在rr_sequential(图3#3中)

 int rr_sequential(READ_RECORD *info)
{
int tmp;
while ((tmp=info->table->file->ha_rnd_next(info->record)))
{
/*
ha_rnd_next can return RECORD_DELETED for MyISAM when one thread is
reading and another deleting without locks.
*/
if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
{
tmp= rr_handle_error(info, tmp);
break;
}
}
return tmp;
}

(23)同样地在ha_rnd_next执行了rnd_next,这些rnd_next都是相同的接口(图3#2是虚函数),其中int ha_perfschema::rnd_next(uchar *buf)

 int ha_perfschema::rnd_next(uchar *buf)
{
DBUG_ENTER("ha_perfschema::rnd_next");
if (!PFS_ENABLED())
{
table->status= STATUS_NOT_FOUND;
DBUG_RETURN(HA_ERR_END_OF_FILE);
} DBUG_ASSERT(m_table);
ha_statistic_increment(&SSV::ha_read_rnd_next_count); int result= m_table->rnd_next();
if (result == )
{
result= m_table->read_row(table, buf, table->field);
if (result == )
stats.records++;
}
table->status= (result ? STATUS_NOT_FOUND : );
DBUG_RETURN(result);
}

这里的uchar *buf就是record

(24)在table_global_status::rnd_next中

 int table_global_status::rnd_next(void)
{
for (m_pos.set_at(&m_next_pos);
m_pos.m_index < m_status_cache.size();
m_pos.next())
{
const Status_variable *status_var= m_status_cache.get(m_pos.m_index);
if (status_var != NULL)
{
make_row(status_var);
m_next_pos.set_after(&m_pos);
return ;
}
}
return HA_ERR_END_OF_FILE;
}

(25)在PFS_engine_table::read_row中

 /**
Read a table row.
@param table Table handle
@param buf Row buffer
@param fields Table fields
@return 0 on success
*/
int PFS_engine_table::read_row(TABLE *table,
unsigned char *buf,
Field **fields)
{
my_bitmap_map *org_bitmap;
Field *f;
Field **fields_reset; /*
Make sure the table structure is as expected before mapping
hard wired columns in read_row_values.
*/
if (! m_share_ptr->m_checked)
{
return HA_ERR_TABLE_NEEDS_UPGRADE;
} /* We must read all columns in case a table is opened for update */
bool read_all= !bitmap_is_clear_all(table->write_set); /* We internally write to Fields to support the read interface */
org_bitmap= dbug_tmp_use_all_columns(table, table->write_set); /*
Some callers of the storage engine interface do not honor the
f->is_null() flag, and will attempt to read the data itself.
A known offender is mysql_checksum_table().
For robustness, reset every field.
*/
for (fields_reset= fields; (f= *fields_reset) ; fields_reset++)
f->reset(); int result= read_row_values(table, buf, fields, read_all);
dbug_tmp_restore_column_map(table->write_set, org_bitmap); return result;
}

首先会把fields里的元素清空,然后通过read_row_values将新值赋给QEP_TAB的fields,

 int table_global_variables
::read_row_values(TABLE *table,
unsigned char *buf,
Field **fields,
bool read_all)
{
Field *f; if (unlikely(! m_row_exists))
return HA_ERR_RECORD_DELETED; /* Set the null bits */
DBUG_ASSERT(table->s->null_bytes == );
buf[]= ; for (; (f= *fields) ; fields++)
{
if (read_all || bitmap_is_set(table->read_set, f->field_index))
{
switch(f->field_index)
{
case : /* VARIABLE_NAME */
set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
break;
case : /* VARIABLE_VALUE */
set_field_varchar_utf8(f, m_row.m_variable_value.m_str, m_row.m_variable_value.m_length);
break;
default:
DBUG_ASSERT(false);
}
}
} return ;
}

(26)在end_send中

 /*****************************************************************************
DESCRIPTION
Functions that end one nested loop iteration. Different functions
are used to support GROUP BY clause and to redirect records
to a table (e.g. in case of SELECT into a temporary table) or to the
network client.
See the enum_nested_loop_state enumeration for the description of return
values.
*****************************************************************************/ /* ARGSUSED */
static enum_nested_loop_state
end_send(JOIN *join, QEP_TAB *qep_tab, bool end_of_records)
{
DBUG_ENTER("end_send");
/*
When all tables are const this function is called with jointab == NULL.
This function shouldn't be called for the first join_tab as it needs
to get fields from previous tab. Note that qep_tab may be one past the last of qep_tab! So don't read its
pointed content. But you can read qep_tab[-1] then.
*/
DBUG_ASSERT(qep_tab == NULL || qep_tab > join->qep_tab);
//TODO pass fields via argument
List<Item> *fields= qep_tab ? qep_tab[-].fields : join->fields; if (!end_of_records)
{
int error; if (join->tables &&
// In case filesort has been used and zeroed quick():
(join->qep_tab[].quick_optim() &&
join->qep_tab[].quick_optim()->is_loose_index_scan()))
{
// Copy non-aggregated fields when loose index scan is used.
if (copy_fields(&join->tmp_table_param, join->thd))
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
}
// Use JOIN's HAVING for the case of tableless SELECT.
if (join->having_cond && join->having_cond->val_int() == )
DBUG_RETURN(NESTED_LOOP_OK); // Didn't match having
error=;
if (join->do_send_rows)
error= join->select_lex->query_result()->send_data(*fields);
if (error)
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ ++join->send_records;
if (join->send_records >= join->unit->select_limit_cnt &&
!join->do_send_rows)
{
/*
If we have used Priority Queue for optimizing order by with limit,
then stop here, there are no more records to consume.
When this optimization is used, end_send is called on the next
join_tab.
*/
if (join->order &&
join->calc_found_rows &&
qep_tab > join->qep_tab &&
qep_tab[-].filesort &&
qep_tab[-].filesort->using_pq)
{
DBUG_PRINT("info", ("filesort NESTED_LOOP_QUERY_LIMIT"));
DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT);
}
}
if (join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
if (join->calc_found_rows)
{
QEP_TAB *first= &join->qep_tab[];
if ((join->primary_tables == ) &&
!join->sort_and_group &&
!join->send_group_parts &&
!join->having_cond &&
!first->condition() &&
!(first->quick()) &&
(first->table()->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
(first->ref().key < ))
{
/* Join over all rows in table; Return number of found rows */
TABLE *table= first->table(); if (table->sort.has_filesort_result())
{
/* Using filesort */
join->send_records= table->sort.found_records;
}
else
{
table->file->info(HA_STATUS_VARIABLE);
join->send_records= table->file->stats.records;
}
}
else
{
join->do_send_rows= ;
if (join->unit->fake_select_lex)
join->unit->fake_select_lex->select_limit= ;
DBUG_RETURN(NESTED_LOOP_OK);
}
}
DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); // Abort nicely
}
else if (join->send_records >= join->fetch_limit)
{
/*
There is a server side cursor and all rows for
this fetch request are sent.
*/
DBUG_RETURN(NESTED_LOOP_CURSOR_LIMIT);
}
}
DBUG_RETURN(NESTED_LOOP_OK);
}

将QEP_TAB中的fields通过send_data直接将数据发送给客户端。

二、show global status的核心数据

上面花了很大的篇幅讲了show global status的目前已知的生成过程

1.all_status_vars的来源

(1)我们可以在sql/sql_show中找到它的定义

Status_var_array all_status_vars();

all_status_vars是SHOW_VAR(详见第一章2(21))的数组

typedef std::vector<st_mysql_show_var> Status_var_array;

(2)all_status_vars加载了数据库的操作状态和所有存储引擎的状态

通过以下两个函数:

1)在sql/mysqld.cc加载了数据库的操作状态

   /*
Add server status variables to the dynamic list of
status variables that is shown by SHOW STATUS.
Later, in plugin_init, and mysql_install_plugin
new entries could be added to that list.
*/
if (add_status_vars(status_vars))
return ; // an error was already reported

2)在sql/sql_plugin.cc中的plugin_initialize加载了所有存储引擎的状态

   if (plugin->plugin->status_vars)
{
if (add_status_vars(plugin->plugin->status_vars))
goto err;
}

2.状态加载

(1)数据库的操作状态

1)status_vars

可以直接看到加载的是status_vars,这里做个计数,

除了一个array,还有DUG_OFF的3项,以及EMBEDDED_LIBRARY,为125项。

 SHOW_VAR status_vars[]= {
{"Aborted_clients", (char*) &aborted_threads, SHOW_LONG, SHOW_SCOPE_GLOBAL},
#ifndef EMBEDDED_LIBRARY
{"Aborted_connects", (char*) &show_aborted_connects, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#endif
#ifdef HAVE_REPLICATION
#ifndef DBUG_OFF
{"Ongoing_anonymous_gtid_violating_transaction_count",(char*) &show_ongoing_anonymous_gtid_violating_transaction_count, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#endif//!DBUG_OFF
{"Ongoing_anonymous_transaction_count",(char*) &show_ongoing_anonymous_transaction_count, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#ifndef DBUG_OFF
{"Ongoing_automatic_gtid_violating_transaction_count",(char*) &show_ongoing_automatic_gtid_violating_transaction_count, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#endif//!DBUG_OFF
#endif//HAVE_REPLICATION
{"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Binlog_stmt_cache_use", (char*) &binlog_stmt_cache_use, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Com", (char*) com_status_vars, SHOW_ARRAY, SHOW_SCOPE_ALL},
{"Com_stmt_reprepare", (char*) offsetof(STATUS_VAR, com_stmt_reprepare), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"Compression", (char*) &show_net_compression, SHOW_FUNC, SHOW_SCOPE_SESSION},
{"Connections", (char*) &show_thread_id_count, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#ifndef EMBEDDED_LIBRARY
{"Connection_errors_accept", (char*) &show_connection_errors_accept, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Connection_errors_internal", (char*) &connection_errors_internal, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Connection_errors_max_connections", (char*) &show_connection_errors_max_connection, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Connection_errors_peer_address", (char*) &connection_errors_peer_addr, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Connection_errors_select", (char*) &show_connection_errors_select, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Connection_errors_tcpwrap", (char*) &show_connection_errors_tcpwrap, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#endif
{"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Created_tmp_tables", (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_discover", (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_external_lock", (char*) offsetof(STATUS_VAR, ha_external_lock_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_mrr_init", (char*) offsetof(STATUS_VAR, ha_multi_range_read_init_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_prepare", (char*) offsetof(STATUS_VAR, ha_prepare_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_read_first", (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_read_key", (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_read_last", (char*) offsetof(STATUS_VAR, ha_read_last_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_read_next", (char*) offsetof(STATUS_VAR, ha_read_next_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_read_prev", (char*) offsetof(STATUS_VAR, ha_read_prev_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_read_rnd", (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_read_rnd_next", (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_rollback", (char*) offsetof(STATUS_VAR, ha_rollback_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_savepoint", (char*) offsetof(STATUS_VAR, ha_savepoint_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_update", (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Key_blocks_not_flushed", (char*) offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG, SHOW_SCOPE_GLOBAL},
{"Key_blocks_unused", (char*) offsetof(KEY_CACHE, blocks_unused), SHOW_KEY_CACHE_LONG, SHOW_SCOPE_GLOBAL},
{"Key_blocks_used", (char*) offsetof(KEY_CACHE, blocks_used), SHOW_KEY_CACHE_LONG, SHOW_SCOPE_GLOBAL},
{"Key_read_requests", (char*) offsetof(KEY_CACHE, global_cache_r_requests), SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
{"Key_reads", (char*) offsetof(KEY_CACHE, global_cache_read), SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
{"Key_write_requests", (char*) offsetof(KEY_CACHE, global_cache_w_requests), SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
{"Key_writes", (char*) offsetof(KEY_CACHE, global_cache_write), SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
{"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS, SHOW_SCOPE_SESSION},
{"Last_query_partial_plans", (char*) offsetof(STATUS_VAR, last_query_partial_plans),SHOW_LONGLONG_STATUS, SHOW_SCOPE_SESSION},
#ifndef EMBEDDED_LIBRARY
{"Locked_connects", (char*) &locked_account_connection_count, SHOW_LONG, SHOW_SCOPE_GLOBAL},
#endif
{"Max_execution_time_exceeded", (char*) offsetof(STATUS_VAR, max_execution_time_exceeded), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Max_execution_time_set", (char*) offsetof(STATUS_VAR, max_execution_time_set), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Max_execution_time_set_failed", (char*) offsetof(STATUS_VAR, max_execution_time_set_failed), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Max_used_connections", (char*) &Connection_handler_manager::max_used_connections, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Max_used_connections_time",(char*) &show_max_used_connections_time, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Open_table_definitions", (char*) &show_table_definitions, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Open_tables", (char*) &show_open_tables, SHOW_FUNC, SHOW_SCOPE_ALL},
{"Opened_files", (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Queries", (char*) &show_queries, SHOW_FUNC, SHOW_SCOPE_ALL},
{"Questions", (char*) offsetof(STATUS_VAR, questions), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Select_full_join", (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Select_full_range_join", (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Select_range", (char*) offsetof(STATUS_VAR, select_range_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Select_range_check", (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Select_scan", (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Slave_open_temp_tables", (char*) &show_slave_open_temp_tables, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#ifdef HAVE_REPLICATION
{"Slave_retried_transactions",(char*) &show_slave_retried_trans, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Slave_heartbeat_period", (char*) &show_heartbeat_period, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Slave_last_heartbeat", (char*) &show_slave_last_heartbeat, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#ifndef DBUG_OFF
{"Slave_rows_last_search_algorithm_used",(char*) &show_slave_rows_last_search_algorithm_used, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#endif
{"Slave_running", (char*) &show_slave_running, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#endif
#ifndef EMBEDDED_LIBRARY
{"Slow_launch_threads", (char*) &Per_thread_connection_handler::slow_launch_threads, SHOW_LONG, SHOW_SCOPE_ALL},
#endif
{"Slow_queries", (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Sort_merge_passes", (char*) offsetof(STATUS_VAR, filesort_merge_passes), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Sort_range", (char*) offsetof(STATUS_VAR, filesort_range_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Sort_rows", (char*) offsetof(STATUS_VAR, filesort_rows), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Sort_scan", (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
#ifdef HAVE_OPENSSL
#ifndef EMBEDDED_LIBRARY
{"Ssl_accept_renegotiates", (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_accepts", (char*) &show_ssl_ctx_sess_accept, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_callback_cache_hits", (char*) &show_ssl_ctx_sess_cb_hits, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_cipher", (char*) &show_ssl_get_cipher, SHOW_FUNC, SHOW_SCOPE_ALL},
{"Ssl_cipher_list", (char*) &show_ssl_get_cipher_list, SHOW_FUNC, SHOW_SCOPE_ALL},
{"Ssl_client_connects", (char*) &show_ssl_ctx_sess_connect, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_ctx_verify_depth", (char*) &show_ssl_ctx_get_verify_depth, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_ctx_verify_mode", (char*) &show_ssl_ctx_get_verify_mode, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_default_timeout", (char*) &show_ssl_get_default_timeout, SHOW_FUNC, SHOW_SCOPE_ALL},
{"Ssl_finished_accepts", (char*) &show_ssl_ctx_sess_accept_good, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_finished_connects", (char*) &show_ssl_ctx_sess_connect_good, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_session_cache_hits", (char*) &show_ssl_ctx_sess_hits, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_session_cache_mode", (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_session_cache_size", (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_sessions_reused", (char*) &show_ssl_session_reused, SHOW_FUNC, SHOW_SCOPE_ALL},
{"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Ssl_verify_depth", (char*) &show_ssl_get_verify_depth, SHOW_FUNC, SHOW_SCOPE_ALL},
{"Ssl_verify_mode", (char*) &show_ssl_get_verify_mode, SHOW_FUNC, SHOW_SCOPE_ALL},
{"Ssl_version", (char*) &show_ssl_get_version, SHOW_FUNC, SHOW_SCOPE_ALL},
{"Ssl_server_not_before", (char*) &show_ssl_get_server_not_before, SHOW_FUNC, SHOW_SCOPE_ALL},
{"Ssl_server_not_after", (char*) &show_ssl_get_server_not_after, SHOW_FUNC, SHOW_SCOPE_ALL},
#ifndef HAVE_YASSL
{"Rsa_public_key", (char*) &show_rsa_public_key, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#endif
#endif
#endif /* HAVE_OPENSSL */
{"Table_locks_immediate", (char*) &locks_immediate, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Table_locks_waited", (char*) &locks_waited, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Table_open_cache_hits", (char*) offsetof(STATUS_VAR, table_open_cache_hits), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Table_open_cache_misses", (char*) offsetof(STATUS_VAR, table_open_cache_misses), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
{"Table_open_cache_overflows",(char*) offsetof(STATUS_VAR, table_open_cache_overflows), SHOW_LONGLONG_STATUS,SHOW_SCOPE_ALL},
{"Tc_log_max_pages_used", (char*) &tc_log_max_pages_used, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Tc_log_page_size", (char*) &tc_log_page_size, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Tc_log_page_waits", (char*) &tc_log_page_waits, SHOW_LONG, SHOW_SCOPE_GLOBAL},
#ifndef EMBEDDED_LIBRARY
{"Threads_cached", (char*) &Per_thread_connection_handler::blocked_pthread_count, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
#endif
{"Threads_connected", (char*) &Connection_handler_manager::connection_count, SHOW_INT, SHOW_SCOPE_GLOBAL},
{"Threads_created", (char*) &show_num_thread_created, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Threads_running", (char*) &show_num_thread_running, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Uptime", (char*) &show_starttime, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#ifdef ENABLED_PROFILING
{"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
#endif
{NullS, NullS, SHOW_LONG, SHOW_SCOPE_ALL}
};

2)com_status_vars

由于我们看过函数PFS_status_variable_cache::manifest的加载过程,我们知道遇到array类型需要继续加载,对于com_status_vars,统计下为147项。

 SHOW_VAR com_status_vars[]= {
{"admin_commands", (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"assign_to_keycache", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ASSIGN_TO_KEYCACHE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"alter_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"alter_db_upgrade", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB_UPGRADE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"alter_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_EVENT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"alter_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_FUNCTION]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"alter_instance", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_INSTANCE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"alter_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_PROCEDURE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"alter_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_SERVER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"alter_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"alter_tablespace", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLESPACE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"alter_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_USER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"analyze", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"begin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"binlog", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BINLOG_BASE64_EVENT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"call_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CALL]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"change_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"change_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_MASTER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"change_repl_filter", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_REPLICATION_FILTER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"check", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECK]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"checksum", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"commit", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMMIT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_EVENT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SPFUNCTION]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_PROCEDURE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SERVER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TRIGGER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_udf", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_USER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"create_view", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_VIEW]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"dealloc_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"delete", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"delete_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"do", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DO]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"drop_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_DB]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"drop_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_EVENT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"drop_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"drop_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"drop_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_PROCEDURE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"drop_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_SERVER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"drop_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"drop_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TRIGGER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"drop_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"drop_view", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_VIEW]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"empty_query", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"explain_other", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXPLAIN_OTHER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"flush", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"get_diagnostics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GET_DIAGNOSTICS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"grant", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"ha_close", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"ha_open", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"ha_read", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"help", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HELP]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"insert", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"insert_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"install_plugin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSTALL_PLUGIN]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"kill", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"load", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"lock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"optimize", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"preload_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"prepare_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PREPARE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"purge", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"purge_before_date", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE_BEFORE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"release_savepoint", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RELEASE_SAVEPOINT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"rename_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"rename_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_USER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"repair", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPAIR]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"replace", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"replace_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"reset", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"resignal", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESIGNAL]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"revoke", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"revoke_all", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"rollback_to_savepoint",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK_TO_SAVEPOINT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"savepoint", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"set_option", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"signal", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SIGNAL]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_binlog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_binlogs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_charsets", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_collations", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_create_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_EVENT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_create_func", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_FUNC]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_create_proc", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_PROC]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_create_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_TRIGGER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_databases", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_engine_logs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_LOGS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_engine_mutex", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_MUTEX]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_engine_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_errors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_fields", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_function_code", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FUNC_CODE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_plugins", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_privileges", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_procedure_code", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROC_CODE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_procedure_status",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_PROC]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_processlist", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_profile", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_profiles", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILES]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_relaylog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_RELAYLOG_EVENTS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_slave_hosts", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_slave_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_table_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_triggers", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"show_create_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_USER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"shutdown", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHUTDOWN]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"slave_stop", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"group_replication_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_START_GROUP_REPLICATION]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"group_replication_stop", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_STOP_GROUP_REPLICATION]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"stmt_execute", (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"stmt_close", (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"stmt_fetch", (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"stmt_prepare", (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"stmt_reset", (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"stmt_send_long_data", (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"truncate", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"uninstall_plugin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNINSTALL_PLUGIN]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"unlock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"update", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"update_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE_MULTI]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"xa_commit", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_COMMIT]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"xa_end", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_END]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"xa_prepare", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_PREPARE]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"xa_recover", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"xa_rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{"xa_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
{NullS, NullS, SHOW_LONG, SHOW_SCOPE_ALL}
};

(2)所有存储引擎的状态

存储引擎是这样声明的,

以存储引擎perfschema为例:

 mysql_declare_plugin(perfschema)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&pfs_storage_engine,
pfs_engine_name,
"Marc Alff, Oracle", /* Formerly Sun Microsystems, formerly MySQL */
"Performance Schema",
PLUGIN_LICENSE_GPL,
pfs_init_func, /* Plugin Init */
pfs_done_func, /* Plugin Deinit */
0x0001 /* 0.1 */,
pfs_status_vars, /* status variables */
NULL, /* system variables */
NULL, /* config options */
, /* flags */
}
mysql_declare_plugin_end;

可以看到

 #ifndef MYSQL_DYNAMIC_PLUGIN
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int PSIZE= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin DECLS[]= {
#else
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin _mysql_plugin_declarations_[]= {
#endif #define mysql_declare_plugin(NAME) \
__MYSQL_DECLARE_PLUGIN(NAME, \
builtin_ ## NAME ## _plugin_interface_version, \
builtin_ ## NAME ## _sizeof_struct_st_plugin, \
builtin_ ## NAME ## _plugin)

主要的数据结构是struct st_mysql_plugin

 /*
Plugin description structure.
*/ struct st_mysql_plugin
{
int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */
void *info; /* pointer to type-specific plugin descriptor */
const char *name; /* plugin name */
const char *author; /* plugin author (for I_S.PLUGINS) */
const char *descr; /* general descriptive text (for I_S.PLUGINS) */
int license; /* the plugin license (PLUGIN_LICENSE_XXX) */
int (*init)(MYSQL_PLUGIN); /* the function to invoke when plugin is loaded */
int (*deinit)(MYSQL_PLUGIN);/* the function to invoke when plugin is unloaded */
unsigned int version; /* plugin version (for I_S.PLUGINS) */
struct st_mysql_show_var *status_vars;
struct st_mysql_sys_var **system_vars;
void * __reserved1; /* reserved for dependency checking */
unsigned long flags; /* flags for plugin */
};

创建的这个函数通过cmake与mysql_mandatory_plugins项关联,在通过函数plugin_init加载到系统中

在文件cmake/plugin.cmake中

   SET(THIS_PLUGIN_REFERENCE " builtin_${target}_plugin,")
IF(ARG_NOT_FOR_EMBEDDED)
SET(THIS_PLUGIN_REFERENCE "
#ifndef EMBEDDED_LIBRARY
${THIS_PLUGIN_REFERENCE}
#endif
")
ENDIF()
SET(PLUGINS_IN_THIS_SCOPE
"${PLUGINS_IN_THIS_SCOPE}${THIS_PLUGIN_REFERENCE}") IF(ARG_MANDATORY)
SET (mysql_mandatory_plugins
"${mysql_mandatory_plugins} ${PLUGINS_IN_THIS_SCOPE}"
PARENT_SCOPE)
ELSE()
SET (mysql_optional_plugins
"${mysql_optional_plugins} ${PLUGINS_IN_THIS_SCOPE}"
PARENT_SCOPE)
ENDIF()

1.perfschema存储引擎

在storage/perfschema/ha_perfschema.cc有pfs_status_vars总共30项

 static struct st_mysql_show_var pfs_status_vars[]=
{
{"Performance_schema_mutex_classes_lost",
(char*) &mutex_class_lost, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Performance_schema_rwlock_classes_lost",
(char*) &rwlock_class_lost, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Performance_schema_cond_classes_lost",
(char*) &cond_class_lost, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Performance_schema_thread_classes_lost",
(char*) &thread_class_lost, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Performance_schema_file_classes_lost",
(char*) &file_class_lost, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Performance_schema_socket_classes_lost",
(char*) &socket_class_lost, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Performance_schema_memory_classes_lost",
(char*) &memory_class_lost, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
{"Performance_schema_mutex_instances_lost",
(char*) &show_func_mutex_instances_lost, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{"Performance_schema_rwlock_instances_lost",
(char*) &global_rwlock_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_cond_instances_lost",
(char*) &global_cond_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_thread_instances_lost",
(char*) &global_thread_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_file_instances_lost",
(char*) &global_file_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_file_handles_lost",
(char*) &file_handle_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_socket_instances_lost",
(char*) &global_socket_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_locker_lost",
(char*) &locker_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
/* table shares, can be flushed */
{"Performance_schema_table_instances_lost",
(char*) &global_table_share_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
/* table handles, can be flushed */
{"Performance_schema_table_handles_lost",
(char*) &global_table_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
/* table lock stats, can be flushed */
{"Performance_schema_table_lock_stat_lost",
(char*) &global_table_share_lock_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
/* table index stats, can be flushed */
{"Performance_schema_index_stat_lost",
(char*) &global_table_share_index_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_hosts_lost",
(char*) &global_host_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_users_lost",
(char*) &global_user_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_accounts_lost",
(char*) &global_account_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_stage_classes_lost",
(char*) &stage_class_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_statement_classes_lost",
(char*) &statement_class_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_digest_lost",
(char*) &digest_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_session_connect_attrs_lost",
(char*) &session_connect_attrs_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_program_lost",
(char*) &global_program_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_nested_statement_lost",
(char*) &nested_statement_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_prepared_statements_lost",
(char*) &global_prepared_stmt_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"Performance_schema_metadata_lock_lost",
(char*) &global_mdl_container.m_lost, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}
};

2.innodb存储引擎

在storage/innobase/handler/ha_innodb.cc中有innodb_status_variables,这里除了DUB为51项

 static SHOW_VAR innodb_status_variables[]= {
{"buffer_pool_dump_status",
(char*) &export_vars.innodb_buffer_pool_dump_status, SHOW_CHAR, SHOW_SCOPE_GLOBAL},
{"buffer_pool_load_status",
(char*) &export_vars.innodb_buffer_pool_load_status, SHOW_CHAR, SHOW_SCOPE_GLOBAL},
{"buffer_pool_resize_status",
(char*) &export_vars.innodb_buffer_pool_resize_status, SHOW_CHAR, SHOW_SCOPE_GLOBAL},
{"buffer_pool_pages_data",
(char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_bytes_data",
(char*) &export_vars.innodb_buffer_pool_bytes_data, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_pages_dirty",
(char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_bytes_dirty",
(char*) &export_vars.innodb_buffer_pool_bytes_dirty, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_pages_flushed",
(char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_pages_free",
(char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG, SHOW_SCOPE_GLOBAL},
#ifdef UNIV_DEBUG
{"buffer_pool_pages_latched",
(char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG, SHOW_SCOPE_GLOBAL},
#endif /* UNIV_DEBUG */
{"buffer_pool_pages_misc",
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_pages_total",
(char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_read_ahead_rnd",
(char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_read_ahead",
(char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_read_ahead_evicted",
(char*) &export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_read_requests",
(char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_reads",
(char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_wait_free",
(char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"buffer_pool_write_requests",
(char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"data_fsyncs",
(char*) &export_vars.innodb_data_fsyncs, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"data_pending_fsyncs",
(char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"data_pending_reads",
(char*) &export_vars.innodb_data_pending_reads, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"data_pending_writes",
(char*) &export_vars.innodb_data_pending_writes, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"data_read",
(char*) &export_vars.innodb_data_read, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"data_reads",
(char*) &export_vars.innodb_data_reads, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"data_writes",
(char*) &export_vars.innodb_data_writes, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"data_written",
(char*) &export_vars.innodb_data_written, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"dblwr_pages_written",
(char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"dblwr_writes",
(char*) &export_vars.innodb_dblwr_writes, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"log_waits",
(char*) &export_vars.innodb_log_waits, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"log_write_requests",
(char*) &export_vars.innodb_log_write_requests, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"log_writes",
(char*) &export_vars.innodb_log_writes, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"os_log_fsyncs",
(char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"os_log_pending_fsyncs",
(char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"os_log_pending_writes",
(char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"os_log_written",
(char*) &export_vars.innodb_os_log_written, SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
{"page_size",
(char*) &export_vars.innodb_page_size, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"pages_created",
(char*) &export_vars.innodb_pages_created, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"pages_read",
(char*) &export_vars.innodb_pages_read, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"pages_written",
(char*) &export_vars.innodb_pages_written, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"row_lock_current_waits",
(char*) &export_vars.innodb_row_lock_current_waits, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"row_lock_time",
(char*) &export_vars.innodb_row_lock_time, SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
{"row_lock_time_avg",
(char*) &export_vars.innodb_row_lock_time_avg, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"row_lock_time_max",
(char*) &export_vars.innodb_row_lock_time_max, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"row_lock_waits",
(char*) &export_vars.innodb_row_lock_waits, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"rows_deleted",
(char*) &export_vars.innodb_rows_deleted, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"rows_inserted",
(char*) &export_vars.innodb_rows_inserted, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"rows_read",
(char*) &export_vars.innodb_rows_read, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"rows_updated",
(char*) &export_vars.innodb_rows_updated, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"num_open_files",
(char*) &export_vars.innodb_num_open_files, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"truncated_status_writes",
(char*) &export_vars.innodb_truncated_status_writes, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"available_undo_logs",
(char*) &export_vars.innodb_available_undo_logs, SHOW_LONG, SHOW_SCOPE_GLOBAL},
#ifdef UNIV_DEBUG
{"purge_trx_id_age",
(char*) &export_vars.innodb_purge_trx_id_age, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"purge_view_trx_id_age",
(char*) &export_vars.innodb_purge_view_trx_id_age, SHOW_LONG, SHOW_SCOPE_GLOBAL},
{"ahi_drop_lookups",
(char*) &export_vars.innodb_ahi_drop_lookups, SHOW_LONG, SHOW_SCOPE_GLOBAL},
#endif /* UNIV_DEBUG */
{NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}
};

innodb_status_variables_export,这里的调用的函数是为了显示innodb_status_variables的内容。

 static SHOW_VAR innodb_status_variables_export[]= {
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
{NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}
};

这样共计353项,这样我们找到了有关于show global status所有的项目,功德圆满了,接下来提取相关数据结构,相关数据结构的数据是否实时更新就好了。

3.相关数据结构

在sql/sql_class.h

 typedef struct system_status_var
{
/* IMPORTANT! See first_system_status_var definition below. */
ulonglong created_tmp_disk_tables;
ulonglong created_tmp_tables;
ulonglong ha_commit_count;
ulonglong ha_delete_count;
ulonglong ha_read_first_count;
ulonglong ha_read_last_count;
ulonglong ha_read_key_count;
ulonglong ha_read_next_count;
ulonglong ha_read_prev_count;
ulonglong ha_read_rnd_count;
ulonglong ha_read_rnd_next_count;
/*
This number doesn't include calls to the default implementation and
calls made by range access. The intent is to count only calls made by
BatchedKeyAccess.
*/
ulonglong ha_multi_range_read_init_count;
ulonglong ha_rollback_count;
ulonglong ha_update_count;
ulonglong ha_write_count;
ulonglong ha_prepare_count;
ulonglong ha_discover_count;
ulonglong ha_savepoint_count;
ulonglong ha_savepoint_rollback_count;
ulonglong ha_external_lock_count;
ulonglong opened_tables;
ulonglong opened_shares;
ulonglong table_open_cache_hits;//缓存使用数?
ulonglong table_open_cache_misses;//缓存丢失数?
ulonglong table_open_cache_overflows;
ulonglong select_full_join_count;
ulonglong select_full_range_join_count;
ulonglong select_range_count;
ulonglong select_range_check_count;
ulonglong select_scan_count;
ulonglong long_query_count; //慢查询数
ulonglong filesort_merge_passes;
ulonglong filesort_range_count;
ulonglong filesort_rows;
ulonglong filesort_scan_count;//全表扫描数?
/* Prepared statements and binary protocol. */
ulonglong com_stmt_prepare;
ulonglong com_stmt_reprepare;
ulonglong com_stmt_execute;
ulonglong com_stmt_send_long_data;
ulonglong com_stmt_fetch;
ulonglong com_stmt_reset;
ulonglong com_stmt_close; ulonglong bytes_received; //接受数据量
ulonglong bytes_sent; //发送数据量 ulonglong max_execution_time_exceeded;
ulonglong max_execution_time_set;
ulonglong max_execution_time_set_failed; /* Number of statements sent from the client. */
ulonglong questions; //总请求数 ulong com_other;
ulong com_stat[(uint) SQLCOM_END];//查询数,更新数,删除数,插入数 /*
IMPORTANT! See last_system_status_var definition below. Variables after
'last_system_status_var' cannot be handled automatically by add_to_status()
and add_diff_to_status().
*/
double last_query_cost;
ulonglong last_query_partial_plans; } STATUS_VAR;

在inlcude/my_sqlcommand.h

 enum enum_sql_command {
SQLCOM_SELECT, // 查询数
SQLCOM_CREATE_TABLE,
SQLCOM_CREATE_INDEX,
SQLCOM_ALTER_TABLE,
SQLCOM_UPDATE, //更新数
SQLCOM_INSERT, //插入数
SQLCOM_INSERT_SELECT,
SQLCOM_DELETE, //删除数
SQLCOM_TRUNCATE,
SQLCOM_DROP_TABLE,
SQLCOM_DROP_INDEX,
SQLCOM_SHOW_DATABASES,
SQLCOM_SHOW_TABLES,
SQLCOM_SHOW_FIELDS,
SQLCOM_SHOW_KEYS,
SQLCOM_SHOW_VARIABLES,
SQLCOM_SHOW_STATUS,
SQLCOM_SHOW_ENGINE_LOGS,
SQLCOM_SHOW_ENGINE_STATUS,
SQLCOM_SHOW_ENGINE_MUTEX,
SQLCOM_SHOW_PROCESSLIST,
SQLCOM_SHOW_MASTER_STAT,
SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS,
SQLCOM_SHOW_CREATE,
SQLCOM_SHOW_CHARSETS,
SQLCOM_SHOW_COLLATIONS,
SQLCOM_SHOW_CREATE_DB,
SQLCOM_SHOW_TABLE_STATUS,
SQLCOM_SHOW_TRIGGERS,
SQLCOM_LOAD,
SQLCOM_SET_OPTION,
SQLCOM_LOCK_TABLES,
SQLCOM_UNLOCK_TABLES,
SQLCOM_GRANT,
SQLCOM_CHANGE_DB,
SQLCOM_CREATE_DB,
SQLCOM_DROP_DB,
SQLCOM_ALTER_DB,
SQLCOM_REPAIR,
SQLCOM_REPLACE, //覆盖数
SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION,
SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,
SQLCOM_OPTIMIZE,
SQLCOM_CHECK,
SQLCOM_ASSIGN_TO_KEYCACHE,
SQLCOM_PRELOAD_KEYS,
SQLCOM_FLUSH,
SQLCOM_KILL,
SQLCOM_ANALYZE,
SQLCOM_ROLLBACK,
SQLCOM_ROLLBACK_TO_SAVEPOINT,
SQLCOM_COMMIT,
SQLCOM_SAVEPOINT,
SQLCOM_RELEASE_SAVEPOINT,
SQLCOM_SLAVE_START,
SQLCOM_SLAVE_STOP,
SQLCOM_START_GROUP_REPLICATION,
SQLCOM_STOP_GROUP_REPLICATION,
SQLCOM_BEGIN,
SQLCOM_CHANGE_MASTER,
SQLCOM_CHANGE_REPLICATION_FILTER,
SQLCOM_RENAME_TABLE,
SQLCOM_RESET,
SQLCOM_PURGE,
SQLCOM_PURGE_BEFORE,
SQLCOM_SHOW_BINLOGS,
SQLCOM_SHOW_OPEN_TABLES,
SQLCOM_HA_OPEN,
SQLCOM_HA_CLOSE,
SQLCOM_HA_READ,
SQLCOM_SHOW_SLAVE_HOSTS,
SQLCOM_DELETE_MULTI,
SQLCOM_UPDATE_MULTI,
SQLCOM_SHOW_BINLOG_EVENTS,
SQLCOM_DO,
SQLCOM_SHOW_WARNS,
SQLCOM_EMPTY_QUERY,
SQLCOM_SHOW_ERRORS,
SQLCOM_SHOW_STORAGE_ENGINES,
SQLCOM_SHOW_PRIVILEGES,
SQLCOM_HELP,
SQLCOM_CREATE_USER,
SQLCOM_DROP_USER,
SQLCOM_RENAME_USER,
SQLCOM_REVOKE_ALL,
SQLCOM_CHECKSUM,
SQLCOM_CREATE_PROCEDURE,
SQLCOM_CREATE_SPFUNCTION,
SQLCOM_CALL,
SQLCOM_DROP_PROCEDURE,
SQLCOM_ALTER_PROCEDURE,
SQLCOM_ALTER_FUNCTION,
SQLCOM_SHOW_CREATE_PROC,
SQLCOM_SHOW_CREATE_FUNC,
SQLCOM_SHOW_STATUS_PROC,
SQLCOM_SHOW_STATUS_FUNC,
SQLCOM_PREPARE,
SQLCOM_EXECUTE,
SQLCOM_DEALLOCATE_PREPARE,
SQLCOM_CREATE_VIEW,
SQLCOM_DROP_VIEW,
SQLCOM_CREATE_TRIGGER,
SQLCOM_DROP_TRIGGER,
SQLCOM_XA_START,
SQLCOM_XA_END,
SQLCOM_XA_PREPARE,
SQLCOM_XA_COMMIT,
SQLCOM_XA_ROLLBACK,
SQLCOM_XA_RECOVER,
SQLCOM_SHOW_PROC_CODE,
SQLCOM_SHOW_FUNC_CODE,
SQLCOM_ALTER_TABLESPACE,
SQLCOM_INSTALL_PLUGIN,
SQLCOM_UNINSTALL_PLUGIN,
SQLCOM_BINLOG_BASE64_EVENT,
SQLCOM_SHOW_PLUGINS,
SQLCOM_CREATE_SERVER,
SQLCOM_DROP_SERVER,
SQLCOM_ALTER_SERVER,
SQLCOM_CREATE_EVENT,
SQLCOM_ALTER_EVENT,
SQLCOM_DROP_EVENT,
SQLCOM_SHOW_CREATE_EVENT,
SQLCOM_SHOW_EVENTS,
SQLCOM_SHOW_CREATE_TRIGGER,
SQLCOM_ALTER_DB_UPGRADE,
SQLCOM_SHOW_PROFILE,
SQLCOM_SHOW_PROFILES,
SQLCOM_SIGNAL,
SQLCOM_RESIGNAL,
SQLCOM_SHOW_RELAYLOG_EVENTS,
SQLCOM_GET_DIAGNOSTICS,
SQLCOM_ALTER_USER,
SQLCOM_EXPLAIN_OTHER,
SQLCOM_SHOW_CREATE_USER,
SQLCOM_SHUTDOWN,
SQLCOM_ALTER_INSTANCE,
/* This should be the last !!! */
SQLCOM_END
};

(1)global_status_var

这是一个全局的数据类型,他只在被查询,重置线程时从每个线程统计。

(2)线程中的status_var

这是每个线程中全局的数据类型,它在做各种操作时被实时更新。

上一篇:OutputCache属性详解(四)— SqlDependency


下一篇:HTML中元素的position属性详解