概述
本章,你将学习 MySQL 中有关变量的知识。
变量:变量是计算机内存中的一块区域,用于存储可变化的数据,并通过名称进行标识。
在 Bash 中,变量可划分为:
- 用户自定义变量 - 常用变量。变量的名称、变量的值、变量的类型都可以被改变。
- 环境变量 - 保存的是和系统操作环境相关的数据。默认环境变量的名称不能更改,但可修改其值。除了这些,用户也可以自定义添加属于自己的环境变量。
- 位置参数变量 - 主要用来向脚本当中传递参数或数据,其作用是固定的。位置参数变量的名称不能自定义且只能修改其变量的值。
- 预定义变量 - Bash 当中已经预先定义好的变量,其作用是固定的。预定义变量的变量名不能自定义且大部分情况下只能修改其变量的值,少部分预定义变量是只读的(变量名与变量值都不能被改变,典型例子如
$BASH_VERSION
)
Bash 中有变量,MySQL 当中也有自己的变量,划分为三类:
- 系统变量(System Variables)
- 用户变量(User-Defined Variables)
- 局部变量(Local Variables)
系统变量
系统变量:即由 MySQL 这样的系统提供的变量。在启动 MySQL 服务实例时,会提供一组赋予默认值的系统变量给使用者使用。根据范围的不同,可划分为:
- 全局级(Global) - 在不重启当前 MySQL 实例的情况下,针对所有的连接会话全局生效
- 会话级(Session)- 仅针对当前的连接会话
查看系统变量
# 查看所有全局级系统变量。要查看会话级系统变量,请将 global 关键字替换为 session。
show global variables;
# 筛选全局级系统变量。要筛选会话级系统变量,请将 global 关键字替换为 session。
show global variables like '%client%';
+---------------------------------------------+---------+
| Variable_name | Value |
+---------------------------------------------+---------+
| character_set_client | utf8mb4 |
| mysqlx_deflate_max_client_compression_level | 5 |
| mysqlx_lz4_max_client_compression_level | 8 |
| mysqlx_zstd_max_client_compression_level | 11 |
+---------------------------------------------+---------+
4 rows in set (0.01 sec)
# 查看特定全局级系统变量的值。要查看会话级系统变量的值,请将 global 替换为 session。
select @@global.character_set_client;
+-------------------------------+
| @@global.character_set_client |
+-------------------------------+
| utf8mb4 |
+-------------------------------+
1 row in set (0.00 sec)
session
关键字省略时,代表会话级系统变量,例如:
show variables;
show variables like '%client%';
select @@character_set_client;
修改系统变量的值
有三种方式修改系统变量的值:
- 通过选项文件 /etc/my.cnf - 永久性修改,重启 MySQL 实例之后生效
- 在 MySQL 的命令行中添加特定的启动选项 - 仅在当前的 MySQL 实例中生效
- 在 MySQL 的交互终端中使用
set
关键字进行设置 - 可在当前连接会话中临时生效(set session
),也可以对之后的连接会话生效(在不重启当前 MySQL 实例的情况下,set global
),也可以写入到持久化文件中。
在 TCL 文档中就修改过:
# 查询当前连接会话的隔离级别
select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ |
+-------------------------+
# 将当前连接会话的隔离级别变更为 read uncommitted
set session transaction isolation level read uncommitted;
通过选项文件修改
选项文件(配置文件)可以存在于多个路径中:
/etc/my.cnf
- 全局/etc/mysql/my.cnf
- 全局/usr/local/mysql8/etc/my.cnf
- 全局~/.my.cnf
- 用于特定用户的局部配置文件
MySQL 在加载配置文件时,会先从全局配置文件加载,然后再加载用户的局部配置文件,若部分系统变量重叠,则以最后读取到的系统变量为准(本质上就是更新或覆盖了同名系统变量的值)。
这一部分的内容可参阅 前面的文档。
通过命令行的启动选项修改
若您的的 MySQL 全局配置文件 /etc/my.cnf 是类似这样的:
[mysqld]
...
user = mysql
max-connections = 700
...
假设您想从命令行启动选项的方式启动新的 MySQL 实例:
Shell > /usr/local/mysql8/bin/mysqld_safe --user=mysql --max-connections=500 &
Q:当这个 MySQL 实例启动后,max-connections 系统变量的值应该是多少?
500。
通过 set
关键字修改
-
仅在当前的连接会话中生效
需要注意!有些系统变量可以被临时修改(
set session
),但有些系统变量必须是全局修改(set global
),比如:# 这是上面的 MySQL 实例 show global variables like 'max_connections'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 500 | +-----------------+-------+ 1 row in set (0.02 sec) set session max_connections=300; ERROR 1229 (HY000): Variable 'max_connections' is a GLOBAL variable and should be set with SET GLOBAL # 但是隔离级别是可以临时修改 set session transaction isolation level read uncommitted; Query OK, 0 rows affected (0.00 sec) select @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | READ-UNCOMMITTED | +-------------------------+ 1 row in set (0.00 sec)
-
对之后的连接会话生效
当前的 MySQL 实例并没有重启。
# 先将上面的连接会话结束掉 quit; # 开启新的连接会话 Shell > /usr/local/mysql8/bin/mysql -u root --password="MyNewPass4!" # 开启了自动提交 show global variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.00 sec) # 全局关闭自动提交 set global autocommit=0; Query OK, 0 rows affected (0.00 sec) # 这并没有改变当前连接会话的自动提交 show session variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.00 sec)
使用另外一个 MySQL 客户端进行连接,开启新的连接会话:
show session variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | OFF | +---------------+-------+ 1 row in set (0.00 sec)
断开上面两个连接会话。
-
写入到持久化文件中
在 MySQL 8.x 版本中引入了新的
persist
和persist_only
关键字,可将set
修改的设置保存到数据目录的 mysqld-auto.cnf 文件中,比如:Shell > /usr/local/mysql8/bin/mysql -u root --password="MyNewPass4!" # 立即生效 set persist max_connections = 1000; quit; # mysqld-auto.cnf 文件会被最后加载,即覆盖掉 /etc/my.cnf 中同名的配置。 Shell > ls -l /usr/local/mysql8/data/mysqld-auto.cnf -rw-r----- 1 mysql mysql 175 Oct 7 19:07 /usr/local/mysql8/data/mysqld-auto.cnf # 文件的格式为 json Shell > cat /usr/local/mysql8/data/mysqld-auto.cnf {"Version": 2, "mysql_dynamic_parse_early_variables": {"max_connections": {"Value": "1000", "Metadata": {"Host": "localhost", "User": "root", "Timestamp": 1759835268746448}}}} Shell > /usr/local/mysql8/bin/mysql -u root --password="MyNewPass4!" # 清空 mysqld-auto.cnf 中的文件内容 reset persist; quit;
persist_only
关键字则会将修改预先存放在 mysqld-auto.cnf,等待下次 MySQL 实例重启时则会生效。Shell > /usr/local/mysql8/bin/mysql -u root --password="MyNewPass4!" # 修改 innodb 存储的缓冲池大小,这里是 2147483648 字节(即 2GB) SET persist_only innodb_buffer_pool_size = 2147483648; quit; Shell > cat /usr/local/mysql8/data/mysqld-auto.cnf {"Version": 2, "mysql_static_variables": {"innodb_buffer_pool_size": {"Value": "2147483648", "Metadata": {"Host": "localhost", "User": "root", "Timestamp": 1759836578655156}}}} Shell > /usr/local/mysql8/bin/mysql -u root --password="MyNewPass4!" # 清空内容 reset persist; # 退出连接会话 quit;
用户变量
声明用户变量并赋值的语法为:
# ":=" 替换为等于号也是可以被接受的语法
set @用户变量名称:=值;
更新已存在的用户变量的值:
# ":=" 替换为等于号也是可以被接受的语法
set @用户变量名称:=值;
查询用户变量的值:
select @用户变量名称;
用户变量的主要作用:
-
存储过程
-
简化冗长的 SQL
比如在前面学习空间数据时:
# 将 WKT 格式的字符串转换为数据库认可的几何对象 set @gdata1:=ST_GeomFromText('point(15 20)'); # 将几何对象插入到表的对应列中 insert into geom values(@gdata1);
-
重复利用,简化操作
只需更新已有用户变量的值即可被用于后续的 SQL 语句
用户变量仅在当前连接会话中生效,一旦退出连接会话,则用户变量自动从内存中释放。
局部变量
局部变量用在 begin...end
代码块中,必须通过 DECLARE
关键字进行显式声明,然后用 set
关键字进行赋值,其语法为:
# 1. 声明
declare 变量名1,变量名2... 类型 [default 值];
# 2. 赋值
set 局部变量名称:=值
# 3. 使用
