MySQL 变量相关

2015-11-09 database mysql

MySQL 通过变量设置来控制不同的行为,以及进行调优,从不同的角度看,定义方式各不相同,例如,如根据能否修改,可以分为动态和静态参数两种,动态参数可以修改,而静态参数是只读。

在本文中简单介绍下 MySQL 中相关变量的设置,以及源码的实现。

简介

MySQL 变量从不同的角度看,定义方式各不相同,例如,如根据能否修改,可以分为动态参数和静态参数两种,动态参数可以修改,而静态参数是只读。

例外,如果按照生命周期/作用域,可以将变量分为 gloal 和 session 两种,有些参数只能在会话中修改 (如 autocommit);有些参数会在整个实例生命周期内生效 (如 binlog_cache_size);有些既可以在会话又可以在整个声明周期内生效 (如 read_buffer_size)。

局部变量

也称为存储过程变量,通过 DECLARE variable_name data_type(size) DEFAULT default_value; 声明,不过只能在 BEGIN/END 声明之间使用。

drop procedure if exists add;
delimiter EOF
create procedure add ( in a int, in b int )
begin
    declare c int default 0;
    set c = a + b;
    select c as c;
end EOF
delimiter ;

用户变量

用户变量的作用域要比局部变量要广,可作用于当前整个连接,但是在当前连接断开后,其所定义的用户变量都会消失。

drop procedure if exists math;
delimiter EOF
create procedure math ( in a int, in b int )
begin
    set @var1 = 1;                   --- 定义用户变量
    set @var2 = 2;
    select @sum:=(a + b) as sum, @dif:=(a - b) as dif;  ---- =select中视为比较操作符
end EOF
delimiter ;

会话变量

服务器为每个连接的客户端维护一系列会话变量,在客户端连接时,使用相应全局变量的当前值对客户端的会话变量进行初始化。

客户端只能更改自己的会话变量,而不能更改其它客户端的会话变量,会话变量的作用域与用户变量一样,仅限于当前连接,当当前连接断开后,其设置的所有会话变量均失效。

可以通过如下的方式设置和查看会话变量。

mysql> SET SESSION var_name = value;            设置会话变量
mysql> SET @@session.var_name = value;
mysql> SET sort_buffer_size = 1024*1024*4;      默认为session级别
mysql> SET sort_buffer_size = default;          恢复默认值

mysql> SELECT @@var_name;                       查看会话变量
mysql> SELECT @@session.var_name;
mysql> SHOW SESSION VARIABLES LIKE "%var%";
mysql> SHOW SESSION VARIABLES;

全局变量

全局变量影响服务器整体操作,当服务器启动时,它将所有全局变量初始化为默认值。这些默认值可以在选项文件中或在命令行中指定的选项进行更改。

要想更改全局变量,必须具有 SUPER 权限,全局变量作用于 server 的整个生命周期,重启后失效;当然,也可以在配置文件中设置。

mysql> SET GLOBAL var_name = value;             设置全局变量,不能省略global,默认为session
mysql> SET @@global.var_name = value;

mysql> SELECT @@global.var_name;
mysql> SHOW GLOBAL VARIABLES LIKE "%var%";
mysql> SHOW GLOBAL VARIABLES;

状态变量

其实就是监控 MySQL 服务器的运行状态,可以通过 show status 命令查看,只能由服务器修改,然后供用户查询。

其它

简单记录下比较容易混淆的地方。

有些变量同时为全局和会话变量,MySQL 将在建立连接时用全局级变量初始化会话级变量,但 一旦连接建立之后,全局级变量的改变不会影响到会话级变量

查看系统变量的值,会优先显示会话级变量的值,如果这个值不存在,则显示全局级变量的值,当然你也可以加上 GLOBAL 或 SESSION/LOCAL 关键字区别。

mysql> show variables like 'log%';
mysql> show variables where variable_name like 'log%' and value='ON';
mysql> show global variables;                                            查看全局变量
mysql> show session/local variables;                                     查看局部变量
mysql> select @@session/local.sql_mode;

全局变量和会话变量可以从 INFORMATION_SCHEMA 数据库里的 GLOBAL_VARIABLES 和 SESSION_VARIABLES 表中获得。

注意:和启动时不一样的是,在运行时设置的变量不允许使用后缀字母 ‘K’、‘M’ 等,但可以用表达式来达到相同的效果,如:SET GLOBAL read_buffer_size = 2*1024*1024

添加变量

当需要扩展 MySQL 时,可能需要通过变量来控制某些功能属性,当然可能在启动 server 时指定参数设置,通过配置文件,或者在运行时修改。

主要分为两种,全局变量控制系统的属性,会对所有的 session 生效;会话变量仅对当前的 session 有效,而对其他的 session 是透明的。

其中有些变量是只能是全局变量,有些既可以是全局的又可以是会话的,

可以通过下面的方式添加变量,添加方式可以详细参考 MySQL源码增加全局变量和会话变量

源码解析

变量的定义在 sql/sys_vars.cc 文件中,

mysqld_main()
 |-init_common_variables()
   |-umask()                          mask设置
   |-tzset()                          时区设置
   |-init_thread_environment()        设置线程的变量
   |-mysql_init_variables()           设置全局变量
   |-ignore_db_dirs_init()
   |-add_status_vars()
   |-log_syslog_init()