MySQL变量分为全局变量、会话变量、用户变量和局部变量。全局变量影响整个服务器,重启后恢复默认;会话变量随连接生成,断开后消失;用户变量连接内自定义,断开失效;局部变量仅在存储过程或函数内有效。
在MySQL开发中,变量类型常常让人困惑。之前处理项目存储过程时,发现代码里既有用 DECLARE 定义的变量(比如 DECLARE cnt INT DEFAULT 0;),也有直接拿来就用的 @count 这种变量,比如 set @count=1;。当时一下子就懵了——这两种变量到底有什么区别?赶紧翻了翻官方文档,又发现还有 @@sql_mode 这种东西。一个圈两个圈的,究竟什么情况?会不会出现三个圈的?

长期稳定更新的攒劲资源: >>>点此立即查看<<<
经过一段时间的测试和文档梳理,现在总算理清了这些变量的区别。通常MySQL中的变量可以分为四类:全局变量、会话变量、用户变量和局部变量。这个分类很常见,我们来逐一看看它们各自的作用。
先说说MySQL服务器本身。它维护着一套系统变量,用来控制运行时的各种行为。这些变量有一部分是编译时就内置在软件里的,还有一部分可以通过外部的配置文件来覆盖。如果想查看所有自编译的内置变量以及能从文件中读取覆盖的变量,可以用下面这条命令:
mysqld --verbose --help
如果想只看自编译的内置变量,可以加上 --no-defaults:
mysqld --no-defaults --verbose --help
简单梳理一下这几类变量的应用范围。MySQL服务器启动时,会先加载软件内置的默认值(写死在代码里的),然后读取配置文件中的变量(如果允许,配置文件的值可以覆盖内置默认值),用这些来初始化整个运行环境。这些存在于内存中的变量,通常就是所谓的全局变量,其中有不少是可以动态修改的。
当有客户端连接到MySQL服务器时,服务器会把全局变量的绝大部分复制一份,作为这个连接的会话变量。这些会话变量和客户端绑定,连接可以修改其中允许修改的部分,但一旦连接断开,这些会话变量就会全部消失。下次重新连接时,又会从全局变量中重新复制一份。
其实和连接相关的变量不只有会话变量,用户变量也是。用户变量就是用户自定义的变量,客户端连接上MySQL后就可以自己定义,整个连接期间有效,断开后消失。
局部变量最好理解,通常用 DECLARE 关键字定义,经常出现在存储过程中,非常像C/C++函数里的局部变量。存储过程的参数其实和它也很相似,基本可以当作同一类变量对待。
全局变量中很多是可以动态调整的,也就是说,在MySQL运行期间,通过 SET 命令就能修改,不需要重启服务。不过,修改大部分全局变量都需要超级权限,比如root账户。
相比之下,会话变量的修改要求低得多,因为修改通常只影响当前连接。但有个别变量是例外,比如 binlog_format 和 sql_log_bin,修改它们也需要较高权限——因为这些设置会影响当前会话的二进制日志记录,可能对服务器复制和备份的完整性造成更广泛的影响。
至于用户变量和局部变量,听名字就知道,它们的生杀大权完全掌握在自己手里,想改就改,不需要理会什么权限,定义和使用都由用户自己控制。
以下给出测试使用的MySQL版本,同时用root用户操作,避免权限问题。
Welcome to the MySQL monitor. Commands end with ; or g.
Your MySQL connection id is 7
Server version: 5.7.21-log MySQL Community Server (GPL)
Copyright © 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
全局变量来源于软件自编译、配置文件和启动参数中指定的变量。其中大部分可以由root用户通过 SET 命令在运行时直接修改,但一旦MySQL服务器重启,所有修改都会被还原。如果修改过配置文件,想恢复最初设置,只需要把配置文件还原,重启服务器即可。
查询所有全局变量:
show global variables;
实战中一般不会这么用,因为结果太多——大概有500多个。通常加个 like 过滤条件:
mysql> show global variables like 'sql%'; +------------------------+----------------------------------------------------------------+ | Variable_name | Value | +------------------------+----------------------------------------------------------------+ | sql_auto_is_null | OFF | | sql_big_selects | ON | | sql_buffer_result | OFF | | sql_log_off | OFF | | sql_mode | STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | | sql_notes | ON | | sql_quote_show_create | ON | | sql_safe_updates | OFF | | sql_select_limit | 18446744073709551615 | | sql_sla ve_skip_counter | 0 | | sql_warnings | OFF | +------------------------+----------------------------------------------------------------+ 11 rows in set, 1 warning (0.00 sec) mysql>
还有一种查询方式是用 select 语句:
select @@global.sql_mode;
当某个全局变量没有会话变量副本时,也可以直接这样查:
select @@max_connections;
设置全局变量也有两种方式:
set global sql_mode='';
或者
set @@global.sql_mode='';
会话变量基本来自全局变量的复制,和客户端连接绑定。无论怎么修改,连接断开后一切都会还原,下次连接时又是一次全新的开始。
类比全局变量,会话变量也有类似的查询方式。查询所有会话变量:
show session variables;
添加过滤条件:
show session variables like 'sql%';
查询特定会话变量,以下三种写法都可以:
select @@session.sql_mode; select @@local.sql_mode; select @@sql_mode;
会话变量的设置方法是最多的,以下方式都可以:
set session sql_mode = ''; set local sql_mode = ''; set @@session.sql_mode = ''; set @@local.sql_mode = ''; set @@sql_mode = ''; set sql_mode = '';
用户变量就是用户自己定义的变量,同样在连接断开时失效。定义和使用比会话变量简单得多。
直接一个 select 语句就可以:
select @count;
设置也相对简单,可以直接用 set 命令:
set @count=1; set @sum:=0;
也可以用 select into 语句来设置值,比如:
select count(id) into @count from items where price < 99;
局部变量通常出现在存储过程中,用于中间计算结果、交换数据等。当存储过程执行完毕,变量的生命周期也就结束了。
也是用 select 语句:
declare count int(4); select count;
与用户变量非常类似:
declare count int(4); declare sum int(4); set count=1; set sum:=0;
也可以用 select into 语句:
declare count int(4); select count(id) into count from items where price < 99;
其实还有一种存储过程参数,也就是C/C++里常说的形参,使用方法和局部变量基本一致,当成局部变量来用就行。
| 操作类型 | 全局变量 | 会话变量 | 用户变量 | 局部变量(参数) |
|---|---|---|---|---|
| 文档常用名 | global variables | session variables | user-defined variables | local variables |
| 出现的位置 | 命令行、函数、存储过程 | 命令行、函数、存储过程 | 命令行、函数、存储过程 | 函数、存储过程 |
| 定义的方式 | 只能查看修改,不能定义 | 只能查看修改,不能定义 | 直接使用,@var形式 | declare count int(4); |
| 有效生命周期 | 服务器重启时恢复默认值 | 断开连接时,变量消失 | 断开连接时,变量消失 | 出了函数或存储过程的作用域,变量无效 |
| 查看所有变量 | show global variables; | show session variables; | - | - |
| 查看部分变量 | show global variables like 'sql%'; | show session variables like 'sql%'; | - | - |
| 查看指定变量 | select @@global.sql_mode、 select @@max_connections; |
select @@session.sql_mode;、 select @@local.sql_mode;、 select @@sql_mode; |
select @var; | select count; |
| 设置指定变量 | set global sql_mode='';、 set @@global.sql_mode=''; |
set session sql_mode = '';、 set local sql_mode = '';、 set @@session.sql_mode = '';、 set @@local.sql_mode = '';、 set @@sql_mode = '';、 set sql_mode = ''; |
set @var=1;、 set @var:=101;、 select 100 into @var; |
set count=1;、 set count:=101;、 select 100 into count; |
看完这个对比表格,之前很多疑惑应该能解开了。如果还有不清楚的地方,或者发现哪里写错了,欢迎指出来,会尽快修正。
select @@变量名 的形式查询。select @@变量名 默认取的是会话变量,如果查询的会话变量不存在,就会获取全局变量,比如 @@max_connections。SET 操作时,set @@变量名=xxx 总是操作会话变量,如果会话变量不存在就会报错。以上内容供大家参考,希望有所帮助。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述