版本
CentOS release 6.7环境下mysql-5.7.16 社区版
概述
mysql可以通过加载配置文件或者在启动时输入命令行参数的方式来完成初始化系统变量、装载插件等操作。本文主要梳理了装载配置文件和命令参数的过程,以及配置文件内容和命令行参数生效的过程。
源码分析
配置文件的读取
load_defaults
mysql在启动过程中调用函数load_defaults来完成配置文件和命令行参数的装载。调用的具体过程如下:
mysqld_main
| load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv)
| my_load_defaults(conf_file, groups, argc, argv, &default_directories)
|
init_default_directories 初始化配置文件路径
|my_search_option_files(conf_file, argc, argv, ......读取配置文件内容
| remaining_argc= argc;
| remaining_argv= argv;
其中MYSQL_CONFIG_NAME为"my"(该宏的值为编译时设置,默认为"my")。argc和argv为main函数的参数,argc为命令行参数数量,argv为命令行参数数组。
函数load_defaults执行结束后,配置文件中所有的参数(所有配置文件依次读取,可能出现重复的参数)和命令行的参数全部存放在参数remaining_argc和remaining_argv中,remaining_argv的格式如下:
remaining_argv[0] --port=30001 配置文件中的参数
...
remaining_argv[n] ----args-separator---- 分隔符
...
remaining_argv[k] --server_id=30001 命令行参数
remaining_argc和remaining_argv为全局变量,供后续初始化变量使用。
init_default_directories
函数init_default_directories为初始化默认配置文件目录函数,会依次将目录加入到数组中。
init_default_directories
| errors += add_directory(alloc, "/etc/", dirs);
| errors += add_directory(alloc, "/etc/mysql/", dirs);
| errors += add_directory(alloc, DEFAULT_SYSCONFDIR, dirs);
| if ((env= getenv("MYSQL_HOME"))) 如果设置了环境变量MYSQL_HOME
errors += add_directory(alloc, env, dirs);
| errors += add_directory(alloc, "", dirs) 为系统变量--defaults-extra-file预留
| errors += add_directory(alloc, "~/", dirs);
其中DEFAULT_SYSCONFDIR为mysql安装目录下的etc目录,如果设置了环境变量MYSQL_HOME,则加入默认目录。
该函数会依次将目录'/etc'、'/etc/mysql'、'/mysql安装目录/etc'、'$MYSQL_HOME'、'~/'作为默认的配置文件路径。
my_search_option_files
函数my_search_option_files根据启动时设置的参数--defaults-file、--no-defaults等,或者在指定位置读取配置文件,或者在默认目录中依次读取配置文件,并将读取到的结果依次缓存下来。
my_search_option_files
| get_defaults_options 读取指定的配置文件参数
/*如果设置了--no-defaults 参数,则忽略--defaults-file 和--defaults-extra-file */
/*如果未设置 --no-defaults,则依次读取--defaults-file 和 --defaults-extra-file */
|*defaults= *argv + sizeof("--defaults-file=")-1;
|*extra_defaults= *argv + sizeof("--defaults-extra-file=")-1;
/*如果设置了参数--defaults-group-suffix和--login-path,则依次读取*/
|*group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
|*login_path= *argv + sizeof("--login-path=")-1;
| if (dirname_length(conf_file)) 如果编译时指定MYSQL_CONFIG_NAME为绝对路径
/*读取指定的配置文件*/
search_default_file(func, func_ctx, NullS, conf_file......
| else if (my_defaults_file) 如果设置了参数--defaults-file(未设置--no-defaults)
/*根据参数的值,读取指定的配置文件*/
search_default_file_with_ext(func, func_ctx, "", "",......
| else if (!found_no_defaults) 如果--defaults-file和--no-defaults均为设置
/*依次在默认目录中,读取my.cnf或者.my.cnf*/
search_default_file(func, func_ctx, *dirs, conf_file ......
配置文件和命令行参数生效
在mysql启动过程中,有两个函数会使配置文件和命令行中的参数生效。
mysql_main
| handle_early_options
| handle_options
| init_common_variables
| get_options(&remaining_argc, &remaining_argv)
| handle_options
在初始化变量过程中,读取到的配置文件和命令行参数会全部存放在全局变量remaining_argc和remaining_argv中,在上述两个函数执行过程中,均使用这两个变量进行变量的初始化。
handle_early_options
有部分系统变量需要在mysqld --initialize时使用,所以越早初始化越好,handle_early_options函数就是为了初始化这部分系统变量。
handle_early_options
/*将系统变量中,属性为PARSE_EARLY的系统变量装载全局变量all_early_options中*/
| sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY);
/*将静态变量my_long_early_options中的值,装载到all_early_options中*/
| for (my_option *opt= my_long_early_options; opt->name != NULL;opt++)
all_early_options.push_back(*opt);
/*将remaining_argv中的变量值,赋值给系统变量*/
| handle_options(&remaining_argc, &remaining_argv, &all_early_options[0], mysqld_get_one_option);
get_options
同样将属性为NORMAL的系统变量和静态系统变量装载全局变量all_options中
get_options
| sys_var_add_options(&all_options, sys_var::PARSE_NORMAL);
| for (my_option *opt= my_long_options; .....
all_options.push_back(*opt);
/*将remaining_argv中的变量值,赋值给系统变量*/
| handle_options(argc_ptr, argv_ptr, &all_options[0], mysqld_get_one_option)))
handle_options
根据输入参数remaining_argc和remaining_argv,更新系统变量的值
handle_options
| my_handle_options
/*将所有的系统变量设为默认值*/
| init_variables(longopts, init_one_value);
/*根据remaining_argv记载的参数名查找对应的系统变量,更新系统变量的值*/
| for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++)
| opt_found= findopt(opt_str, length, &optp) /*根据输入的参数查找系统变量*/
/*根据参数的类型,将输入的参数值进行一系列转换,复制给系统变量*/
| error= setval(optp, optp->value, argument......
/*对不同类型的系统变量做赋值后的特殊处理*/
| get_one_option(optp->id, optp, argument)
在对系统变量进行复制后,会根据系统变量的成员变量id,对系统变量做特殊处理,比如-p参数,会在命令行显示时隐藏真实的值,以x xxx来代替。