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()