(轉)MySQL中全域性變數、會話變數、使用者變數和區域性變數的區別
原文:https://www.modb.pro/db/12232
前言
之前在專案的儲存過程中發現有通過DECLARE
關鍵字定義的變數如DECLARE cnt INT DEFAULT 0;
,還有形如@count
這樣的變數,儲存過程中拿過來直接就進行設定,像這樣set @count=1;
,這兩種型別的變數究竟有什麼區別卻弄不清楚,趕緊上網查詢資料,發現還有@@sql_mode
這樣的變數,這一個圈倆圈的到底是什麼啊?會不會出現三個圈的情況?
變數分類與關係
經過一段時間學習和測試,再配合官方的文件,現在大致弄清楚了這些變數的區別,一般可以將MySQL中的變數分為全域性變數、會話變數、使用者變數和區域性變數,這是很常見的分類方法,這些變數的作用是什麼呢?可以從前往後依次看一下。
首先我們知道MySQL伺服器維護了許多系統變數來控制其執行的行為,這些變數有些是預設編譯到軟體中的,有些是可以通過外部配置檔案來配置覆蓋的,如果想查詢自編譯的內建變數和從檔案中可以讀取覆蓋的變數可以通過以下命令來查詢:
mysqld --verbose --help
如果想只看自編譯的內建變數可以使用命令:
mysqld --no-defaults --verbose --help
接下來簡單瞭解一下這幾類變數的應用範圍,首先MySQL伺服器啟動時會使用其軟體內建的變數(俗稱寫死在程式碼中的)和配置檔案中的變數(如果允許,是可以覆蓋原始碼中的預設值的)來初始化整個MySQL伺服器的執行環境,這些變數通常就是我們所說的全域性變數,這些在記憶體中的全域性變數有些是可以修改的。
當有客戶端連線到MySQL伺服器的時候,MySQL伺服器會將這些全域性變數的大部分複製一份作為這個連線客戶端的會話變數,這些會話變數與客戶端連線繫結,連線的客戶端可以修改其中允許修改的變數,但是當連線斷開時這些會話變數全部消失,重新連線時會從全域性變數中重新複製一份。
其實與連線相關的變數不只有會話變數一種,使用者變數也是這樣的,使用者變數其實就是使用者自定義變數,當客戶端連線上MySQL伺服器之後就可以自己定義一些變數,這些變數在整個連線過程中有效,當連線斷開時,這些使用者變數消失。
區域性變數實際上最好理解,通常由DECLARE
關鍵字來定義,經常出現在儲存過程中,非常類似於C和C++函式中的區域性變數,而儲存過程的引數也和這種變數非常相似,基本上可以作為同一種變數來對待。
變數的修改
先說全域性變數有很多是可以動態調整的,也就是說可以在MySQL伺服器執行期間通過SET
命令修改全域性變數,而不需要重新啟動 MySQL 服務,但是這種方法在修改大部分變數的時候都需要超級許可權,比如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 伺服器重新啟動,所有修改都被還原。如果修改了配置檔案,想恢復最初的設定,只需要將配置檔案還原,重新啟動 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_slave_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; |
相信看了這個對比的表格,之前的很多疑惑就應該清楚了,如果發現其中有什麼疑惑的地方可以給我留言,或者發現有什麼錯誤也可以一針見血的指出來,我會盡快改正的。
總結
- MySQL 中的變數通常分為:全域性變數、 會話變數、 使用者變數、 區域性變數
- 其實還有一個儲存過程和函式的引數,這種型別和區域性變數基本一致,當成區域性變數來使用就行了
- 在表格中有一個容易疑惑的點就是無論是全域性變數還是會話變數都有
select@@變數名
的形式。 select@@變數名
這種形式預設取的是會話變數,如果查詢的會話變數不存在就會獲取全域性變數,比如@@max_connections
- 但是
SET
操作的時候,set @@變數名=xxx
總是操作的會話變數,如果會話變數不存在就會報錯