MySQL Status代码实现

本文将和大家一起看看Status的内部实现机制,相关的代码是基于MySQL 8.0。

MySQL使用了两张Performance_Schema数据库的表,session_statusglobal_status分别对应Session级别以及Global级别的状态信息访问。 两张表的定义如下,包含的字段是一样的。

Show session|global Status命令会在MySQL server层解析成对performance_schema.session_status或者performance_schema.global_status的Select语句。具体参见 build_show_session_statusbuild_show_global_status方法,这两个方法都会调用方法来真正生成对应的SELECT_LEX,之后执行。

Status变量定义见SHOW_VAR结构体

  1. struct SHOW_VAR {
  2. const char *name; //Status名字
  3. char *value; //Status的值
  4. enum enum_mysql_show_type type; //Status类型,比如SHOW_ARRAY, SHOW_LONGLONG,不同的类型Status处理的方法不同
  5. enum enum_mysql_show_scope scope; //Status作用范围,包括 SHOW_SCOPE_UNDEF,SHOW_SCOPE_GLOBAL, SHOW_SCOPE_SESSION和SHOW_SCOPE_ALL
  6. };

SHOW_SCOPE_UNDEF

  • 未定义作用域,。当成SHOW_SCOPE_ALL对待

SHOW_SCOPE_GLOBAL

  • 全局作用域。这种Status在整个MySQL实例生命周期里面只有一个,且全局的值。只可以通过SHOW GLOBAL STATUS,或者Select Performance_Schema.global_status表查看。 例子: Aborted_connects, Binlog_cache_use

SHOW_SCOPE_ALL

  • 这种Status变量可以作用于各自的连接,也会在全局范围做聚集。既可以通过SHOW SESSION STATUS,或者Select Performance_Schema.session_status表查看,也可以通过SHOW GLOBAL STATUS 或者 Select Performance_Schema.global_status查看。 例子: Bytes_sent, Open_tables, Com variables

all_status_vars

在mysqld.cc文件中定义的Status变量的全局动态SHOW_VAR数组,所有的server以及plugin的Status变量都会在里面定义。在MySQL实例初始化阶段,Status变量都会被组装成这个all_status_vars的全局动态数组,plugin在load的时候,带入的新的status变量会被加到这个数组里面。all_status_vars里面包含的Status的定义都是有序的存放的,以方便Show Status命令或者是对相关系统表session_status或者是global_status的访问。

System_status_var

thread级别的status变量,变量类型必须是long/ulong。

Global locks

LOCK_status 是一个全局mutex,它被用来在初始化阶段以及SHOW STATUS执行阶段保护all_status_vars。

Thread locks

在做多个thread Status聚合的时候后,global thread manager会持有两把锁来防止thread被移除。Global_THD_manager::LOCK_thd_remove和。 但,两种锁的持有时间不同,LOCK_thd_remove会在整个聚合执行期间一直持有, LOCK_thd_count 锁 会在当前thread list的快照做了copy之后就会释放。

取session域的Status的调用栈如下

取global域的Status的调用栈如下,和session域的调用栈很类似

  1. join_materialize_derived-> TABLE_LIST::materialize_derived->…
  2. ->ha_perfschema::rnd_init->table_session_status::rnd_init
  3. -> PFS_variable_cache<Status_variable>::materialize_all //Materialize output status
  4. ->PFS_status_variable_cache::do_materialize_all->PFS_status_variable_cache::manifest
  5. join_materialize_derived-> TABLE_LIST::materialize_derived->…
  6. ->ha_perfschema::rnd_next->table_session_status::rnd_next

type为SHOW_FUNC的Status,例如Aborted_connects,访问方法比较特别,会调用SHOW_VAR里面定义的函数来处理,

例如取Aborted_connects,就会调用show_aborted_connects这个函数来获取真正的值。

    MySQL当前的架构已经对Status扩展做了很好的支持。我们如果想添加一个新的Status,一般的步骤是在System_status_var里面添加一个相应的变量,并在status_vars数组里面 也对应添加一个对应的SHOW_VAR条目。需要处理的是对Status 变量做累计,这个就要根据具体的逻辑了。