博客 / 詳情

返回

詳解MySQL 的系統變量、狀態

 

搞懂這三個命令的區別,核心是 變量作用域(全局 / 會話),你的部分理解需要修正 ——show VARIABLES 並非 “疊加”,而是默認顯示「當前會話生效的變量」;session 和 global 變量也並非數量一致,而是有 “僅全局”“僅會話”“兩者都有” 三類情況。下面分步驟講清楚:

一、核心區別:作用域與顯示邏輯

三者的本質差異是 查詢的變量作用域不同,且 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 的優先級

假設場景:
 
  1. 全局變量 sql_mode 為 ''(寬鬆模式);
  2. 你當前會話執行 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'
 
 
結論:同一變量,session 優先級 > global(當前會話優先用自己的配置,沒有則繼承 global)。

三、session 變量 vs global 變量:數量與範圍

你的第二個問題:“session 變量允許有哪些?是不是和 global 一樣多?”
 
答案:不一樣多。MySQL 的變量分為三類,決定了兩者的範圍差異:

1. 僅全局變量(無對應 session 變量)

這類變量是數據庫實例的 “基礎配置”,無法在會話級別修改,只能全局設置。
 
  • 例子:datadir(數據存儲目錄)、port(監聽端口)、max_connections(最大連接數)、innodb_buffer_pool_size(InnoDB 緩衝池大小)。
  • 特點:show SESSION VARIABLES 查不到這些變量,只能通過 show GLOBAL VARIABLES 查看。

2. 僅會話變量(無對應 global 變量)

這類變量和 “當前連接的操作狀態” 相關,僅存在於會話中,不影響全局。
 
  • 例子:insert_id(手動指定的下一個自增 ID)、last_insert_id(當前會話最後插入的自增 ID)、sql_safe_updates(當前會話的安全更新模式)。
  • 特點:show GLOBAL VARIABLES 查不到這些變量,只能通過 show SESSION VARIABLES 查看。

3. 既全局又會話的變量(最常見)

這類變量有全局默認值,每個會話會繼承初始值,但可以在會話中單獨修改(不影響全局)。
 
  • 例子:sql_mode(SQL 模式)、wait_timeout(連接超時時間)、character_set_client(客户端字符集)、max_join_size(關聯查詢的最大行數限制)。
  • 特點:show GLOBAL 和 show SESSION 都能查到,但值可能不同(會話修改後)。

總結數量關係:

session 變量總數 ≠ global 變量總數,兩者有重疊(第三類),但各有獨有的變量(第一、二類)。

四、補充注意點

  1. 全局變量修改後,已存在的會話不生效,只有新連接會繼承新的全局值;
  2. 有些變量即使是 “既全局又會話”,修改 session 級也可能無效(比如 innodb_buffer_pool_size,雖然能查 session 值,但修改後不生效,因為是共享資源,只能全局配置);
  3. 權限要求:修改 global 變量需要 SUPER 權限(或 MySQL 8.0+ 的 SYSTEM_VARIABLES_ADMIN 權限),修改 session 變量一般不需要特殊權限;
  4. 簡寫:show LOCAL VARIABLES 等價於 show SESSION VARIABLES(LOCAL 是 SESSION 的別名)。

最終總結

  1. show GLOBAL VARIABLES:查實例級全局配置,影響所有新連接;
  2. show SESSION VARIABLES:查當前連接的專屬配置,僅影響當前連接;
  3. show VARIABLES:默認查 SESSION 變量,即當前會話正在使用的配置(優先用自己的,沒有則繼承 global);
  4. session 和 global 變量數量不同,有 “僅全局”“僅會話”“兩者都有” 三類,同名變量的會話值會覆蓋全局值(僅當前連接)。

 

如何得知 當前session 有修改過哪些變量? 難道只能一個個的比對嗎
 
 
不需要一個個手動比對!MySQL 提供了 系統表查詢 + 變量來源追蹤 的高效方法,能直接篩選出當前會話中被修改過的變量(即「會話值≠全局默認值」的變量)。以下是兩種最實用的方案,適配不同 MySQL 版本:

核心邏輯

會話變量的初始值默認繼承自全局變量,只有「手動修改過」或「連接時自動適配」的變量,才會和全局值不一致。因此,找出「會話值≠全局值」且「變量同時存在於全局和會話」的記錄,就是當前會話修改過的變量(排除會話獨有變量)。

方案一:通用方案(MySQL 5.7+ 兼容)

利用 information_schema 中的 GLOBAL_VARIABLES 和 SESSION_VARIABLES 兩張系統表,直接關聯比對同名變量的值,差異結果就是修改過的變量。

直接可用的 SQL 語句

sql
 
 
-- 找出當前會話中,與全局值不同的變量(即修改過的變量)
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 自動適配的(比如字符集相關變量,若客户端和全局默認字符集不同)。
  • 排除了「僅全局變量」(如 datadir)和「僅會話變量」(如 last_insert_id),只聚焦於「可修改且有全局默認值」的變量(正是你關心的 “可能被修改” 的變量)。

方案二:精準方案(MySQL 8.0.11+ 推薦)

MySQL 8.0.11 及以上版本,新增了 performance_schema.variables_info 表,其中 VARIABLE_SOURCE 字段直接記錄了「會話變量值的來源」,無需比對,直接篩選來源為 SESSION 的變量即可,更精準高效。

直接可用的 SQL 語句

sql
 
 
-- 精準找出當前會話中「手動修改過」的變量(來源為 SESSION)
SELECT
  VARIABLE_NAME,  -- 變量名
  VARIABLE_VALUE AS SESSION_VALUE,  -- 會話修改後的值
  VARIABLE_SOURCE AS 來源  -- 來源:SESSION=手動修改;GLOBAL=繼承全局;COMMAND_LINE=命令行啓動參數等
FROM
  performance_schema.variables_info
WHERE
  -- VARIABLE_SOURCE 取值説明:
  -- SESSION:會話中手動修改過(核心目標)
  -- GLOBAL:繼承全局默認值(未修改)
  -- COMMAND_LINE:MySQL 啓動時指定的參數
  -- CONFIG_FILE:my.cnf/my.ini 配置文件
  VARIABLE_SOURCE = 'SESSION'
ORDER BY
  VARIABLE_NAME;
 

優勢

  • 無需關聯兩張表,查詢速度更快;
  • 能精準區分「手動修改」(來源 SESSION)和「自動適配 / 繼承」(來源 GLOBAL),避免誤判(比如字符集變量可能因客户端配置自動變化,並非手動修改,方案一會列出,方案二可排除)。

補充説明(避坑)

  1. 變量類型比對問題:
     
    部分變量的全局值和會話值類型可能不同(比如 max_connections 是數字,sql_mode 是字符串),方案一中用 CAST(xxx AS CHAR) 統一轉成字符串比對,避免因類型差異導致的 “假陽性”(比如 123 和 '123' 本應相等,卻因類型不同被判為不同)。
  2. 會話獨有變量的處理:
     
    方案一用 INNER JOIN 只保留「既有全局又有會話」的變量,自動排除了 last_insert_id 這類「僅會話變量」(它們不存在全局值,自然不屬於 “修改自全局” 的範疇),無需額外過濾。
  3. 權限要求:
     
    兩種方案都需要 SELECT 權限(對 information_schema 或 performance_schema),普通用户默認擁有(除非管理員特意限制),無需 SUPER 權限。
  4. 修改後不生效的變量:
     
    有些變量(比如 innodb_buffer_pool_size)雖然能 SET SESSION 修改,但實際不生效(因為是全局共享資源),但這兩個方案依然會列出它們(只要會話值≠全局值或來源為 SESSION),需注意這類變量的 “修改” 僅為表面值,未實際生效。

總結

  • 若使用 MySQL 8.0.11+,優先用 方案二(精準、高效,直接定位手動修改的變量);
  • 若使用 MySQL 5.7 及以下,用 方案一(兼容所有版本,能找出所有與全局值不同的變量);
  • 兩種方案都無需手動比對,直接運行 SQL 即可得到結果,高效解決你的問題。

 

我是否可以理解為,當啓動一個mysql 會話即session的時候, 會創建MySQL的一個session實例,然後 會自動從global實例中繼承一些變量(是繼承全部嗎),然後按需對其中某些變量進行修改,(哪些是可以修改、哪些不能修改的呢?)如不修改, 那麼直接去global的變量?
 
 
你的理解大體方向正確,但有幾個關鍵細節需要修正和補充,核心結論先明確:
 
  1. 會話(session)啓動時不會繼承全部 global 變量,只繼承「既全局又會話的變量」的初始值;
  2. 不修改會話變量時,用的是「啓動時繼承的全局初始值」(而非實時讀取 global 變量);
  3. 變量能否修改,取決於它的「類型」和「MySQL 的設計規則」(不是所有變量都能改會話級)。
 
下面分步驟把邏輯講透,貼合你的 MySQL 5.7.11 版本:

一、先明確:會話啓動時的變量 “初始化邏輯”(不是 “繼承全部”)

你説的 “session 實例啓動時繼承 global 變量”,本質是 會話變量的初始化過程,但繼承範圍有限,具體分 3 類(沿用之前的變量分類,保持一致):
 
變量類型 會話啓動時的初始化邏輯 舉例
1. 僅全局變量(無 session 版) 會話中不存在該變量,既不能繼承,也不能修改(會話根本查不到) datadir(數據目錄)、port(端口)、max_connections(最大連接數)
2. 僅會話變量(無 global 版) 會話啓動時自動創建,值來自 MySQL 的 “會話默認規則”(和 global 無關),只能改會話級 last_insert_id(當前會話最後插入的自增 ID)、insert_id(手動指定的自增 ID)
3. 既全局又會話的變量(最常見) 會話啓動時,複製當前 global 變量的 “實時值” 作為初始值(相當於 “快照”),之後可獨立修改 sql_mode(SQL 模式)、wait_timeout(連接超時)、character_set_client(客户端字符集)

關鍵修正你的誤解:

  • 不是 “繼承全部 global 變量”:僅第 3 類變量會被會話 “複製初始值”,第 1 類僅全局變量會話根本沒有,談不到繼承;
  • 不是 “實時讀取 global 變量”:會話啓動後,第 3 類變量的初始值就和 global 變量 “脱鈎” 了 —— 之後哪怕修改了 global 變量,已存在的會話也不會同步(新會話才會用新的 global 值當初始值)。
 
舉個直觀例子:
 
  1. 全局變量 wait_timeout = 86400(默認 24 小時);
  2. 你啓動一個新會話(session A),會話的 wait_timeout 初始值 = 86400(複製當時的 global 值);
  3. 之後管理員修改全局變量 SET GLOBAL wait_timeout = 3600(1 小時);
  4. 會話 A 的 wait_timeout 依然是 86400(不受 global 修改影響),只有新啓動的會話 B,才會以 3600 作為初始值。

二、哪些變量能修改?哪些不能?(分場景説清楚)

變量能否修改,核心看「變量類型」和「MySQL 的設計限制」,按 “修改範圍”(會話級 / 全局級)分類如下:

1. 僅能修改全局級(會話級不能改,也不存在會話值)

  • 對應變量類型:第 1 類(僅全局變量);
  • 特點:和數據庫實例的 “基礎配置 / 共享資源” 相關,必須全局統一,不能按會話自定義;
  • 例子:datadir(數據目錄)、port(端口)、max_connections(最大連接數)、innodb_buffer_pool_size(InnoDB 緩衝池);
  • 説明:show SESSION VARIABLES 查不到這些變量,只能用 SET GLOBAL xxx 修改(需 SUPER 權限),且新會話才生效。

2. 僅能修改會話級(全局級不存在,或不能改)

  • 對應變量類型:第 2 類(僅會話變量)+ 部分第 3 類(既全局又會話,但全局級不允許改);
  • 特點:和當前會話的 “操作狀態” 相關,僅影響當前連接,不涉及全局資源;
  • 例子:
    • 僅會話變量:last_insert_id(只能通過插入數據或 SET SESSION last_insert_id = xxx 修改)、sql_safe_updates(僅會話級生效,控制是否允許無 WHERE 的 UPDATE/DELETE);
    • 第 3 類但僅能改會話級:character_set_results(客户端字符集返回格式,全局改意義不大,通常改會話級);
  • 説明:修改無需特殊權限,SET SESSION xxx 即可,斷開連接後失效。

3. 既能改全局級,也能改會話級(最常見)

  • 對應變量類型:大部分第 3 類(既全局又會話的變量);
  • 特點:有全局默認值,也支持會話自定義,滿足 “全局統一 + 局部靈活” 的需求;
  • 例子:sql_mode(SQL 模式,全局寬鬆 + 會話嚴格)、wait_timeout(連接超時,全局 24 小時 + 會話 1 小時)、max_join_size(關聯查詢最大行數限制)、sort_buffer_size(排序緩衝區大小);
  • 説明:
    • 改全局:SET GLOBAL xxx(需 SUPER 權限),新會話生效;
    • 改會話:SET SESSION xxx(普通權限),僅當前會話生效,不影響全局。

4. 特殊情況:能改但不生效(坑點)

有些第 3 類變量(既全局又會話),雖然能執行 SET SESSION xxx,但修改後實際不生效 —— 因為它們是 “全局共享資源”,會話級修改被 MySQL 忽略;
 
  • 例子:innodb_buffer_pool_size(緩衝池大小)、key_buffer_size(MyISAM 索引緩衝區);
  • 説明:這些變量的會話值只是 “顯示用”,實際生效的還是全局值,改會話級沒用。

三、補充:不修改會話變量時,取值邏輯是什麼?

你問 “如不修改,那麼直接去 global 的變量?”—— 這個理解不準確,正確邏輯是:
 
  1. 對於第 3 類變量(既全局又會話):不修改的話,用的是「會話啓動時複製的 global 初始值」(不是實時去讀 global);
  2. 對於第 2 類變量(僅會話變量):不修改的話,用的是「MySQL 的會話默認值」(和 global 無關);
  3. 對於第 1 類變量(僅全局變量):會話中根本查不到,不存在 “取值” 一説。
 
再舉個例子驗證:
 
  1. 全局 sql_mode = ''(寬鬆模式);
  2. 啓動會話 A,會話 A 的 sql_mode 初始值 = ''(複製當時的 global 值);
  3. 管理員修改全局 sql_mode = STRICT_TRANS_TABLES(嚴格模式);
  4. 會話 A 不修改自己的 sql_mode,此時查詢 show VARIABLES like 'sql_mode',結果還是 ''(不是實時讀新的 global 值);
  5. 新啓動會話 B,其 sql_mode 初始值 = STRICT_TRANS_TABLES(複製新的 global 值)。

四、最終總結(幫你梳理核心邏輯)

  1. 會話啓動時,僅「既全局又會話的變量」會複製當前 global 值作為初始值,僅全局變量不繼承,僅會話變量自動創建;
  2. 不修改會話變量時,用的是 “初始值”(第 3 類 = 複製的 global 初始值,第 2 類 = 會話默認值),和後續 global 變量的修改無關;
  3. 變量能否修改:
    • 僅全局變量:只能改 global(需權限,新會話生效);
    • 僅會話變量:只能改 session(無權限限制,當前會話生效);
    • 既全局又會話的變量:大部分能改兩者,少數改 session 不生效;
  4. 你的核心理解 “會話繼承部分 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 實際運行的效果,兩者是 “因” 與 “果” 的關聯,但本質完全不同。

一、核心區別:用表格直觀對比(適配你的 MySQL 5.7.11)

對比維度 variables(變量 / 配置項) STATUS(狀態 / 監控數據)
本質 運行規則 / 參數設置(“遊戲規則”) 運行時的實時數據 / 統計結果(“遊戲戰況”)
用途 控制 MySQL 行為(比如字符集、超時時間、SQL 模式) 監控 MySQL 狀態(比如連接數、查詢量、緩存命中率)、排查問題
讀寫性 大部分可修改(SET GLOBAL/SESSION),少數只讀(如 datadir 完全只讀(只能查詢,不能修改,數據由 MySQL 自動統計更新)
生命週期 全局變量:實例啓動時加載(配置文件 / 命令行),修改後重啓 / 新連接生效;會話變量:連接生命週期 全局狀態:實例啓動後開始累計;會話狀態:連接啓動後開始累計,斷開連接後數據重置
作用域 支持 GLOBAL(實例級)和 SESSION(連接級),部分僅全局 / 僅會話 支持 GLOBAL(全實例累計)和 SESSION(當前連接累計),部分僅全局(如 Uptime
數據類型 字符串、數字、布爾等(配置值) 多為數字(統計計數)、少數字符串(如 Version
查詢命令 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)是否合理。
 
舉 2 個直觀關聯例子:
 
  1. 配置 max_connections(variables)= 100 → 狀態 Threads_connected(STATUS)的最大值不會超過 100(如果超過,會出現 “連接數滿” 錯誤);
  2. 配置 sql_mode(variables)= STRICT_TRANS_TABLES(嚴格模式)→ 狀態 Com_insert(STATUS)中,因數據不符合規則導致的插入失敗數會增加(可結合錯誤日誌查看);
  3. 配置 wait_timeout(variables)= 3600 → 狀態 Threads_connected(STATUS)中,閒置超過 1 小時的連接會被自動斷開,連接數會減少。

四、關鍵避坑:這些細節別混淆

  1. 作用域一致性≠含義一致:
     
    兩者都支持 GLOBAL 和 SESSION,但含義不同:
    • show SESSION VARIABLES like 'wait_timeout':當前連接的超時規則(比如 3600 秒);
    • show SESSION STATUS like 'Threads_connected':當前連接的活躍狀態(固定為 1,因為是當前連接自己)。
  2. STATUS 是 “累計值”,不是 “實時快照”:
     
    比如 Queries 是從實例 / 連接啓動後開始累計的,不是 “當前正在執行的查詢數”(當前執行數看 Threads_running)。
  3. 部分 STATUS 變量名和 variables 類似,但完全不同:
     
    比如 version(STATUS)是 MySQL 版本號(狀態),version_comment(variables)是版本註釋(配置),名稱接近但含義無關。

五、總結:什麼時候用哪個?

  • 想「改規則、調配置」→ 用 variables(比如修改字符集、調整超時時間、開啓嚴格模式);
  • 想「看狀態、查問題」→ 用 STATUS(比如排查連接數滿、找慢查詢、監控緩存效果);
  • 核心邏輯:用 variables 定規則,用 STATUS 看規則的執行效果,兩者配合才能完整掌控 MySQL 的運行。
 
比如你之前想知道 “會話修改了哪些變量”,用 variables 對比;現在想知道 “修改後連接數是否下降”,就用 STATUS 查 Threads_connected —— 這就是兩者的實際配合場景。
 
 
 
如下的區別? show GLOBAL STATUS; show SESSION STATUS; show STATUS;
 
  
 
這三個命令的核心區別和 variables 系列完全一致 ——默認行為 + 統計數據的作用域(全局 / 會話),結合你熟悉的 MySQL 5.7.11 版本,用 “統計範圍 + 實際用途” 就能講透,還能直接對應到你的運維場景:

一、核心區別:一張表説清(延續之前的對比邏輯,好理解)

命令 作用域 統計範圍(數據來源) 典型用途
show GLOBAL STATUS 全局(實例級) 從 MySQL 實例啓動後開始 累計 的全實例數據(所有連接的彙總統計) 監控整個數據庫的運行狀態(比如總連接數、全實例慢查詢數、服務器運行時長)
show SESSION STATUS 會話(連接級) 從當前連接啓動後開始 累計 的專屬數據(僅當前連接的操作統計) 排查當前連接的問題(比如當前連接執行了多少 SQL、當前連接的慢查詢數)
show STATUS 默認 = 會話級(省略 SESSION) 等價於 show SESSION STATUS,僅顯示 當前連接的累計統計數據 快速查看當前連接的操作狀態(比如剛執行的 SQL 有沒有觸發慢查詢)

關鍵結論(和 variables 邏輯對齊,易記):

  • show STATUS 沒有 “疊加”,默認只看「當前會話」的統計;
  • 全局狀態是 “全實例彙總”,會話狀態是 “當前連接單獨統計”,互不干擾;
  • 數據都是 累計值(從實例 / 連接啓動時開始算),不是實時 “快照”(比如 Queries 是累計執行的 SQL 總數,不是當前正在執行的數量)。

二、直觀例子:執行後看差異(直接複製到你的 5.7.11 測試)

假設場景:你的 MySQL 實例已運行 1000 秒,當前有 3 個活躍連接,你當前連接剛執行了 5 條 SQL,其中 1 條是慢查詢。

1. 查全局狀態(全實例彙總)

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

  1. 部分狀態變量只有 “全局版”,沒有會話版:
     
    比如 Uptime(實例運行時長)、Com_show_databases(全實例累計執行 show databases 的次數),執行 show SESSION STATUS like 'Uptime' 也能查到,但值是「當前連接的存活時長」(不是實例時長),用途不同。
  2. 會話狀態的生命週期:
     
    會話狀態數據從連接建立時開始累計,斷開連接後數據會重置(下次重連重新從 0 開始算);而全局狀態數據從實例啓動時開始累計,重啓實例才會重置。
  3. 別把 “累計值” 當 “實時值”:
    • 想查 “當前正在執行的 SQL 數”→ 用 show GLOBAL STATUS like 'Threads_running'(全局),不是 Queries(累計總數);
    • 想查 “當前活躍連接數”→ 用 show GLOBAL STATUS like 'Threads_connected'(全局),不是 Threads_running(正在執行的連接數)。
  4. 權限要求:
     
    普通用户默認能查 SESSION STATUS;查 GLOBAL STATUS 可能需要 PROCESS 權限(如果報錯 “Access denied”,讓管理員授予 GRANT PROCESS ON *.* TO '你的用户名'@'localhost';)。

四、實際使用場景(什麼時候用哪個?)

需求場景 推薦命令 原因
查看數據庫總連接數、總慢查詢數 show GLOBAL STATUS 需全實例彙總數據
排查當前連接的 SQL 執行情況(比如 “我剛執行的 SQL 有沒有算慢查詢”) show SESSION STATUS / show STATUS 只需當前連接的統計數據
監控數據庫運行時長、整體緩存命中率 show GLOBAL STATUS 全局累計數據才有意義
測試當前連接的參數效果(比如修改 sql_safe_updates 後,看當前連接的更新語句數) show SESSION STATUS 僅關注當前連接的操作結果

最終總結(一句話記牢)

  • show GLOBAL STATUS:看 “整個數據庫的累計戰況”;
  • show SESSION STATUS:看 “你當前連接的累計戰況”;
  • show STATUS:簡寫 = SESSION STATUS,懶人的 “個人戰況” 查詢;
  • 核心還是「作用域」,和之前 variables 系列的命令邏輯完全一致,不用額外記新規則~
  • show SESSION VARIABLES; = show LOCAL VARIABLES;(兩者完全一樣)。
     

 

 

user avatar u_16163452 頭像 AllBigFish 頭像 u_16120231 頭像 u_17585566 頭像
4 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.