mysql系统变量存储

以下语句
 select @@read_buffer_size;
mysql最终是如何解析的呢?
yacc的归纳过程如下:
select_item——>remember_name expr remember_end select_alias——>expr——>bool_pri——>predicate——>bit_expr——>simple_expr——>variable——>variable_aux

variable_aux:
          ident_or_text SET_VAR expr
          {
            Item_func_set_user_var *item;
            $$= item=
              new (YYTHD->mem_root) Item_func_set_user_var($1, $3, false);
            if ($$ == NULL)
              MYSQL_YYABORT;
            LEX *lex= Lex;
            lex->uncacheable(UNCACHEABLE_RAND);
            lex->set_var_list.push_back(item);
          }
        | ident_or_text
          {
            $$= new (YYTHD->mem_root) Item_func_get_user_var($1);
            if ($$ == NULL)
              MYSQL_YYABORT;
            LEX *lex= Lex;
            lex->uncacheable(UNCACHEABLE_RAND);
          }
        | '@' opt_var_ident_type ident_or_text opt_component
          {
            /* disallow "SELECT @@global.global.variable" */
            if ($3.str && $4.str && check_reserved_words(&$3))
            {
              my_parse_error(ER(ER_SYNTAX_ERROR));
              MYSQL_YYABORT;
            }
            if (!($$= get_system_var(YYTHD, $2, $3, $4)))
              MYSQL_YYABORT;
            if (!((Item_func_get_system_var*) $$)->is_written_to_binlog())
              Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE);
          }
        ;

get_system_var函数用来查找系统变量,返回结果是item类型,因为select中的字段的类型是item的子类
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
             LEX_STRING component)

内部调用find_sys_var不查找系统变量
sys_var *find_sys_var(THD *thd, const char *str, uint length)
{
  sys_var *var;
  sys_var_pluginvar *pi= NULL;
  plugin_ref plugin;
  DBUG_ENTER("find_sys_var");

  mysql_mutex_lock(&LOCK_plugin);
  mysql_rwlock_rdlock(&LOCK_system_variables_hash);
  if ((var= intern_find_sys_var(str, length)) &&
      (pi= var->cast_pluginvar()))
  {
    mysql_rwlock_unlock(&LOCK_system_variables_hash);
    LEX *lex= thd ? thd->lex : 0;
    if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
      var= NULL; /* failed to lock it, it must be uninstalling */
    else
    if (!(plugin_state(plugin) & PLUGIN_IS_READY))
    {
      /* initialization not completed */
      var= NULL;
      intern_plugin_unlock(lex, plugin);
    }
  }
  else
    mysql_rwlock_unlock(&LOCK_system_variables_hash);
  mysql_mutex_unlock(&LOCK_plugin);

  if (!var)
    my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
  DBUG_RETURN(var);
}

find_sys_var调用intern_find_sys_var查找系统变量
sys_var *intern_find_sys_var(const char *str, uint length)
{
  sys_var *var;

  /*
    This function is only called from the sql_plugin.cc.
    A lock on LOCK_system_variable_hash should be held
  */
  var= (sys_var*) my_hash_search(&system_variable_hash,
                              (uchar*) str, length ? length : strlen(str));


  /* Don't show non-visible variables. */
  if (var && var->not_visible())
    return NULL;

  return var;
}

即所有的系统变量定义在文件:sql/sys_vars_shared.h文件中
extern sys_var_chain all_sys_vars;
这个变量在何时赋值进行初始的呢?

我们来看如何声明一个变量:打开文件sql/sys_vars.cc,查看变量performance_schema的声明
static Sys_var_mybool Sys_pfs_enabled(
       "performance_schema",
       "Enable the performance schema.",
       READ_ONLY GLOBAL_VAR(pfs_param.m_enabled),
       CMD_LINE(OPT_ARG), DEFAULT(TRUE),
       PFS_TRAILING_PROPERTIES);

这里performance_schema系统变量用类Sys_var_mybool 表示,看这个类的构造函数
class Sys_var_mybool: public Sys_var_typelib
{
public:
  Sys_var_mybool(const char *name_arg,
          const char *comment, int flag_args, ptrdiff_t off, size_t size,
          CMD_LINE getopt,
          my_bool def_val, PolyLock *lock=0,
          enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
          on_check_function on_check_func=0,
          on_update_function on_update_func=0,
          const char *substitute=0,
          int parse_flag= PARSE_NORMAL)
    : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
                      SHOW_MY_BOOL, bool_values, def_val, lock,
                      binlog_status_arg, on_check_func, on_update_func,
                      substitute, parse_flag)
  {
……
这个类继承自Sys_var_typelib,再看这个类的构造函数
 Sys_var_typelib(const char *name_arg,
          const char *comment, int flag_args, ptrdiff_t off,
          CMD_LINE getopt,
          SHOW_TYPE show_val_type_arg, const char *values[],
          ulonglong def_val, PolyLock *lock,
          enum binlog_status_enum binlog_status_arg,
          on_check_function on_check_func, on_update_function on_update_func,
          const char *substitute, int parse_flag= PARSE_NORMAL)
    : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
              getopt.arg_type, show_val_type_arg, def_val, lock,
              binlog_status_arg, on_check_func,
              on_update_func, substitute, parse_flag)
而Sys_var_typelib又继承自sys_var类,这个时候把all_sys_vars这个全局变量的指针传到sys_var的构造函数中

最后看sys_var类的构造函数
sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
                 const char *comment, int flags_arg, ptrdiff_t off,
                 int getopt_id, enum get_opt_arg_type getopt_arg_type,
                 SHOW_TYPE show_val_type_arg, longlong def_val,
                 PolyLock *lock, enum binlog_status_enum binlog_status_arg,
                 on_check_function on_check_func,
                 on_update_function on_update_func,
                 const char *substitute, int parse_flag) :
  next(0),
  binlog_status(binlog_status_arg),
  flags(flags_arg), m_parse_flag(parse_flag), show_val_type(show_val_type_arg),
  guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func),
  deprecation_substitute(substitute),
  is_os_charset(FALSE)
{
  /*
    There is a limitation in handle_options() related to short options:
    - either all short options should be declared when parsing in multiple stages,
    - or none should be declared.
    Because a lot of short options are used in the normal parsing phase
    for mysqld, we enforce here that no short option is present
    in the first (PARSE_EARLY) stage.
    See handle_options() for details.
  */
  DBUG_ASSERT(parse_flag == PARSE_NORMAL || getopt_id <= 0 || getopt_id >= 255);

  name.str= name_arg;     // ER_NO_DEFAULT relies on 0-termination of name_arg
  name.length= strlen(name_arg);                // and so does this.
  DBUG_ASSERT(name.length <= NAME_CHAR_LEN);

  memset(&option, 0, sizeof(option));
  option.name= name_arg;
  option.id= getopt_id;
  option.comment= comment;
  option.arg_type= getopt_arg_type;
  option.value= (uchar **)global_var_ptr();
  option.def_value= def_val;

  if (chain->last)
    chain->last->next= this;
  else
    chain->first= this;
  chain->last= this;

}
这里会把新声明的系统变量加到all_sys_vars这个全局变量所指向的链表中
整个类的层次如下,Sys_var_mybool——Sys_var_typelib——sys_var,其中在sys_var这个类中实现将所有系统变量加入到链表中的功能

而添加系统变量调用mysql_add_sys_var_chain来完成的

posted @ 2015-06-20 23:27  szphper  阅读(661)  评论(0)    收藏  举报