mysql源码学习笔记:系统变量variables

来源:互联网 发布:exe视频加密软件 编辑:程序博客网 时间:2024/06/06 02:49

版本

CentOS release 6.7环境下mysql-5.7.16 社区版

概述

mysql维护一系列系统变量,每个变量每个变量控制mysql server或者client的一种或几种行为。变量的具体细节可以参照:https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html

通常使用配置文件、命令行参数、客户端连接修改的方式来修改系统变量的值,后面会具体分析变量的定义、装载、更新等一系列流程。

源码分析

定义

mysql的系统变量以如下方式定义:
1. 定义一个类的对象或者全局结构体变量来存放系统变量的一些属性(sys_vars.cc)
2. 定义一个全局变量来存放系统变量的值

系统变量类

mysql为每种类型的系统变量均定义了一个系统的类,这里以bool型的系统变量为例

/* 所有的系统变量类均为类sys_var的派生类 */class Sys_var_charptr: public sys_var{    /* 构造函数,将参数传入到sys_var的构造函数中 */    Sys_var_mybool(...) :sys_var(&all_sys_vars...)    /* 每个类重载的更新函数、校验函数等等 */    bool session_update(THD *thd, set_var *var)    bool global_update(THD *thd, set_var *var)    bool do_check(THD *thd, set_var *var)    ......} /*所有系统变量的父类 */class sys_var                                {   /* 初始化的更新函数和检查函数 */   typedef bool (*on_check_function)(sys_var *self, THD *thd, set_var *var);   typedef bool (*on_update_function)(sys_var *self, THD *thd, enum_var_type type);   /* 存放变量的最大值、最小值、是否允许命令行等值 */   /* 后续用于装载系统变量时使用的结构体 */   my_option option;   ......   ......}

系统变量(系统变量类对象)

/* 定义一个全局变量用于存放系统变量的值(mysqld.cc)*/char *mysql_home_ptr;/* 定义base_dir系统变量,定义一个char *型的系统变量(sys_vars.cc)*/static Sys_var_charptr Sys_basedir(                                                    "basedir",                                                                                                               /*变量名称 */    "Path to installation directory. All paths are usually resolved relative to this",        /*变量说明 */    READ_ONLY                                           /*设置变量的flag,设置只读           */                                                      GLOBAL_VAR(mysql_home_ptr),           /*设置变量的flag,设置为global, 同时设置该变量的值存放在变量mysql_home_ptr*/    CMD_LINE(REQUIRED_ARG, 'b'),         /*设置命令行属性,指定可以使用命令行设定,同时可以使用-b来设置变量*/    IN_FS_CHARSET,                                  /*字符集相关属性*/    DEFAULT(0));                                         /*默认值*/

关于类的初始化不再具体描述,查看构造函数即可。

全局变量

静态的声明一些全局变量,类型与sys_var中option类型相同,这类系统变量是命令行使用的系统变量。

struct my_option my_long_early_options[]=                                        /*初始化需要加载的系统变量*/{   ...  {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},   ...}struct my_option my_long_options[]={  ...  {"autocommit", 0, "Set default value for autocommit (0 or 1)",   &opt_autocommit, &opt_autocommit, 0,   GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, NULL},  ...}

对于一些类型的系统变量类不支持命令行,需要在这个全局变量中增加同名的变量。、
如Sys_var_bit类不允许执行命令行,那么使用这个类定义的对象autocommit,就需要在全局变量my_long_options中增加同名的变量来支持命令行参数。

class Sys_var_bit: public Sys_var_typelib                  {  Sys_var_bit(const char *name_arg,......  {    ...    DBUG_ASSERT(getopt.id == -1); /* force NO_CMD_LINE  不支持命令行  */    ...  }}

装载

系统变量类对象

系统变量类在定义一个对象时,在调用构造函数(父类sys_var的构造函数)的过程中,会将该变量存储到一个全局的链表中

class Sys_var_charptr: public sys_var| Sys_var_charptr(const char *name_arg,    | sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,    |    if (chain->last)  chain->last->next= this;    |    else  chain->first= this; chain->last= this;

静态全局变量

静态全局变量是不装载到系统变量链表中,只是在启动时将命令行参数的值更新到系统变量中。show variables是看不到这里声明的系统变量的。

初始化装载

创建一个全局的hash桶,用来存放所有的系统变量。

sever系统变量

mysql_main| sys_var_init      /* 初始化一个全局的系统变量hash桶*/    | if (my_hash_init(&system_variable_hash, system_charset_info, 100, 0,      /* 将所有的系统变量存放到全局hash桶中*/    | mysql_add_sys_var_chain(all_sys_vars.first)        for (var= all_sys_vars.first; var; var= var->next)           my_hash_insert(&system_variable_hash, (uchar*) var)

插件系统变量

/* 启动或者装载插件*/......                                                                              | mysql_install_plugin                                                   /* 装载插件函数*/    | plugin_add       test_plugin_options          mysql_add_sys_var_chain(plugin->system_vars)       /* 增加插件的所有变量*//* 卸载插件时*/......                                                                              | mysql_uninstall_plugin    | reap_plugins         mysql_del_sys_var_chain(plugin->system_vars)         /* 删除插件的所有变量*/

更新

配置文件和命令行更新

配置文件中和命令行中配置的系统变量如何生效这里不再重复介绍,请查看之前的博客文章。

客户端修改系统变量

以客户端设置变量为例,sql语句为set xxxx_var = ‘example’;

解析SQL语句,在解析过程中,判断变量名是否为系统变量

(sql_yacc.yy)set SET start_option_value_listoption_value_no_option_type option_value_list_continuedinternal_variable_name   equal    set_expr_or_default     $$= NEW_PTN PT_internal_variable_name_1d($1);/*定义类PT_internal_variable_name_1d的对象,然后依次嵌套调用函数contextualize */class PT_internal_variable_name_1d : public PT_internal_variable_name{  virtual bool contextualize(Parse_context *pc)  | if (find_sys_var_null_base(thd, &value))      | find_sys_var(thd, tmp->base_name.str, tmp->base_name.length);          | var= intern_find_sys_var(str, length)                    /*在全局hansh桶system_variable_hash中查找变量 */              | var= (sys_var*) my_hash_search(&system_variable_hash,......}

解析后生成需要更新的系统变量的链表,这里的链表元素是使用类set_var的对象:

class set_var :public set_var_base                     /*用来操作系统变量的类 */{    ......    sys_var *var;                                                   /* 系统变量    */    Item *value;                                                     /* 解析出需要更新的值 */    ...    int check(THD *thd);                                        /* 校验函数 */    int update(THD *thd);                                      /* 更新函数 */}

使用类set_var对系统变量进行更新

......mysql_parse  /* 解析SQL语句,生成set的系统变量链表(见上) */| err= parse_sql(thd, parser_state, NULL);  /* 执行SQL语句 */| mysql_execute_command    case SQLCOM_SET_OPTION:    if (!(res= sql_set_variables(thd, lex_var_list)))        |if ((error= var->check(thd)))                    /* set_var的方法check */            /* 这里的var是set_var的成员变量sys_var,即系统变量 */            if (var->is_readonly())                       /* 判断系统变量是否为只读 */            if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))  /*全局变量需要super权限 */        if (var->check_update_type(value->result_type()))        /*校验更新的类型 */            var->check(thd, this)                                                     /*调用变量的校验函数,变量定义时设置 */        | error|= var->update(thd);                    /* set_var的方法update */               /* 如果有设置的值则设置,没有设置的值则设置成默认 */        | return value ? var->update(thd, this) : var->set_default(thd, this);
原创粉丝点击