(轉)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;

相信看了這個對比的表格,之前的很多疑惑就應該清楚了,如果發現其中有什么疑惑的地方可以給我留言,或者發現有什么錯誤也可以一針見血的指出來,我會盡快改正的。

總結

    1. MySQL 中的變量通常分為:全局變量、 會話變量、 用戶變量、 局部變量
    2. 其實還有一個存儲過程和函數的參數,這種類型和局部變量基本一致,當成局部變量來使用就行了
    3. 在表格中有一個容易疑惑的點就是無論是全局變量還是會話變量都有select@@變量名的形式。
    4. select@@變量名這種形式默認取的是會話變量,如果查詢的會話變量不存在就會獲取全局變量,比如@@max_connections
    5. 但是SET操作的時候,set @@變量名=xxx 總是操作的會話變量,如果會話變量不存在就會報錯


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM