三者的本质差异是 查询的变量作用域不同,且 show VARIABLES 有默认行为,具体对比如下:
命令
作用域
含义(显示什么)
生效范围
修改方式(示例)
show GLOBAL VARIABLES
全局(实例级)
MySQL 实例的全局配置,对 所有新连接 生效(已存在的会话不受影响)
整个数据库实例
SET GLOBAL sql_mode = 'XXX';(需 SUPER 权限)
show SESSION VARIABLES
会话(连接级)
当前数据库连接的专属配置,仅对 当前连接 生效(断开连接后失效)
仅当前连接
SET SESSION sql_mode = 'XXX';(普通权限即可)
show VARIABLES
默认 = 会话级(可省略 SESSION)
等价于 show SESSION VARIABLES,显示 当前会话正在使用的变量值
仅当前连接
同 show SESSION VARIABLES
关键纠正你的误解:
不是 “叠加”:show VARIABLES 只显示「当前会话生效的变量」,而非同时显示 global 和 session。
其值的来源是:如果当前会话修改过某个变量,就显示修改后的 session 值;如果没修改过,就显示继承自 global 的默认值。
例:global 的 sql_mode 是 '',当前会话执行 SET SESSION sql_mode = 'STRICT_TRANS_TABLES' 后,show VARIABLES like 'sql_mode' 会显示修改后的 session 值,而非同时显示两个值。
二、直观例子:看懂 session 与 global 的优先级
假设场景:
全局变量 sql_mode 为 ''(宽松模式);
你当前会话执行 SET SESSION sql_mode = 'STRICT_TRANS_TABLES'(严格模式);
此时查询结果:
sql
-- 显示全局配置(未变)
show GLOBAL VARIABLES like 'sql_mode'; -- 结果:''
-- 显示当前会话配置(已修改)
show SESSION VARIABLES like 'sql_mode'; -- 结果:'STRICT_TRANS_TABLES'
-- 等价于上面的 SESSION,显示当前生效的配置
show VARIABLES like 'sql_mode'; -- 结果:'STRICT_TRANS_TABLES'
-- 找出当前会话中,与全局值不同的变量(即修改过的变量)
SELECT
s.VARIABLE_NAME, -- 变量名
g.VALUE AS GLOBAL_VALUE, -- 全局默认值
s.VALUE AS SESSION_VALUE -- 会话修改后的值
FROM
information_schema.GLOBAL_VARIABLES g
INNER JOIN
information_schema.SESSION_VARIABLES s
ON
g.VARIABLE_NAME = s.VARIABLE_NAME -- 只比对「既有全局又有会话」的变量(排除独有变量)
WHERE
-- 注意:用 CAST 统一类型,避免因变量类型不同导致的比对失败(比如数字 vs 字符串)
CAST(g.VALUE AS CHAR) != CAST(s.VALUE AS CHAR)
ORDER BY
s.VARIABLE_NAME;
效果说明
结果会列出所有「会话值≠全局值」的变量,这些变量要么是你手动 SET SESSION 修改的,要么是连接时 MySQL 自动适配的(比如字符集相关变量,若客户端和全局默认字符集不同)。
对于第 3 类变量(既全局又会话):不修改的话,用的是「会话启动时复制的 global 初始值」(不是实时去读 global);
对于第 2 类变量(仅会话变量):不修改的话,用的是「MySQL 的会话默认值」(和 global 无关);
对于第 1 类变量(仅全局变量):会话中根本查不到,不存在 “取值” 一说。
再举个例子验证:
全局 sql_mode = ''(宽松模式);
启动会话 A,会话 A 的 sql_mode 初始值 = ''(复制当时的 global 值);
管理员修改全局 sql_mode = STRICT_TRANS_TABLES(严格模式);
会话 A 不修改自己的 sql_mode,此时查询 show VARIABLES like 'sql_mode',结果还是 ''(不是实时读新的 global 值);
新启动会话 B,其 sql_mode 初始值 = STRICT_TRANS_TABLES(复制新的 global 值)。
四、最终总结(帮你梳理核心逻辑)
会话启动时,仅「既全局又会话的变量」会复制当前 global 值作为初始值,仅全局变量不继承,仅会话变量自动创建;
不修改会话变量时,用的是 “初始值”(第 3 类 = 复制的 global 初始值,第 2 类 = 会话默认值),和后续 global 变量的修改无关;
变量能否修改:
仅全局变量:只能改 global(需权限,新会话生效);
仅会话变量:只能改 session(无权限限制,当前会话生效);
既全局又会话的变量:大部分能改两者,少数改 session 不生效;
你的核心理解 “会话继承部分 global 变量,按需修改,不修改则用初始值” 是对的,只是要注意 “继承范围” 和 “初始值不实时同步 global” 这两个细节。
如果想快速判断某个变量能否改会话级,直接执行 SET SESSION 变量名 = 新值,若报错 Variable 'xxx' is a GLOBAL variable and should be set with SET GLOBAL,说明该变量只能改 global;若不报错,且查询 show VARIABLES like 'xxx' 是新值,说明改 session 级有效~
MySQL 中 STATUS 怎么理解,和 variables 是关系区别?
要理解 MySQL 中 STATUS 和 variables 的关系与区别,核心一句话就能拎清:
variables 是「配置项」(静态规则),STATUS 是「运行状态 / 监控数据」(动态结果) —— 配置项决定 MySQL 如何运行,运行状态反映 MySQL 实际运行的效果,两者是 “因” 与 “果” 的关联,但本质完全不同。
show GLOBAL/SESSION VARIABLES [like 'xxx'];performance_schema.global/session_variables
show GLOBAL/SESSION STATUS [like 'xxx'];performance_schema.global/session_status
二、分别详解:用例子帮你落地理解
1. variables:管 “规则”,决定 MySQL 怎么跑
variables 是你之前一直关注的 “配置”,核心是「提前设定好的规则」,告诉 MySQL 该用什么字符集、允许多少连接、超时多久断开等。
常见例子(既全局又会话的核心变量):
sql_mode:SQL 模式(规则),决定是否允许零日期、是否严格校验数据;
wait_timeout:连接超时时间(规则),决定客户端闲置多久断开;
character_set_client:客户端字符集(规则),决定 MySQL 如何解析客户端发送的字符;
max_connections:最大连接数(规则),决定 MySQL 最多能同时接受多少连接。
查询示例(你之前用过的):
sql
-- 查全局配置(规则)
show GLOBAL VARIABLES like 'sql_mode';
-- 查当前会话配置(规则)
show SESSION VARIABLES like 'wait_timeout';
2. STATUS:管 “结果”,反映 MySQL 跑的怎么样
STATUS 是 MySQL 运行过程中「自动统计的数据」,记录规则执行后的实际效果,比如 “按 max_connections 规则,当前有多少连接在使用”“按 query_cache_type 规则,缓存命中了多少次”。
常见例子(按场景分类):
状态变量名
作用说明(反映的 “结果”)
连接相关
Threads_connected
当前活跃的连接数(全局 / 会话,会话级 = 当前连接数 1)
Threads_running
当前正在执行 SQL 的连接数(排查 “卡库” 常用)
查询相关
Queries
累计执行的 SQL 语句总数(全局 = 全实例,会话 = 当前连接)
Slow_queries
累计执行时间超过 long_query_time(默认 10 秒)的慢查询数(排查慢查询常用)
缓存相关
Qcache_hits
查询缓存命中次数(5.7 支持,8.0 已移除)
Qcache_inserts
查询缓存插入次数
服务器相关
Uptime
MySQL 实例启动后的总秒数(仅全局,监控服务器运行时长)
Com_insert/update/delete
累计执行的插入 / 更新 / 删除语句数(全局 / 会话)
查询示例(适配你的 5.7.11):
sql
-- 查全局状态:当前活跃连接数、总查询数
show GLOBAL STATUS like 'Threads_connected';
show GLOBAL STATUS like 'Queries';
-- 查当前会话状态:当前连接执行的 SQL 数、慢查询数
show SESSION STATUS like 'Queries';
show SESSION STATUS like 'Slow_queries';
三、两者的关联:配置(variables)决定状态(STATUS),状态反映配置效果
variables 和 STATUS 不是孤立的,而是 “因” 与 “果” 的关系 —— 你修改了配置(variables),最终会体现在状态(STATUS)上;通过状态(STATUS),也能反推配置(variables)是否合理。
show GLOBAL STATUS like 'Uptime'; -- 结果:1000(实例运行总秒数,仅全局有)
show GLOBAL STATUS like 'Threads_connected'; -- 结果:3(全实例当前活跃连接数)
show GLOBAL STATUS like 'Queries'; -- 结果:100(全实例所有连接累计执行100条SQL)
show GLOBAL STATUS like 'Slow_queries'; -- 结果:5(全实例所有连接累计5条慢查询)
2. 查当前会话状态(仅你当前连接)
sql
show SESSION STATUS like 'Uptime'; -- 结果:60(当前连接已建立60秒,不是实例时长)
show SESSION STATUS like 'Threads_connected'; -- 结果:1(当前连接自己,固定为1)
show SESSION STATUS like 'Queries'; -- 结果:5(当前连接累计执行5条SQL)
show SESSION STATUS like 'Slow_queries'; -- 结果:1(当前连接累计1条慢查询)
3. 查默认 STATUS(等价于 SESSION)
sql
show STATUS like 'Queries'; -- 结果:5(和 SESSION 完全一致)
show STATUS like 'Slow_queries'; -- 结果:1(和 SESSION 完全一致)
差异一眼懂:
全局状态是 “集体数据”,反映整个数据库的负载;
会话状态是 “个人数据”,只反映你当前连接的操作;
show STATUS 就是偷懒写法,默认看 “个人数据”。
三、关键注意点(避坑,适配 5.7.11)
部分状态变量只有 “全局版”,没有会话版:
比如 Uptime(实例运行时长)、Com_show_databases(全实例累计执行 show databases 的次数),执行 show SESSION STATUS like 'Uptime' 也能查到,但值是「当前连接的存活时长」(不是实例时长),用途不同。