Mysql查詢語句執行過程 Mysql分為server層和存儲引擎兩部分,或許可以再加一層連接層 連接層(器) Mysql使用的是典型的C/S架構。連接器通過典型的TCP握手完成連接。 需要註的是, 如果用戶名和密碼都正確,那麼該連接所擁有的許可權僅僅是連接成功建立時的所讀取到的許可權 這就意味著:當連 ...
Mysql查詢語句執行過程
Mysql分為server層
和存儲引擎
兩部分,或許可以再加一層連接層
連接層(器)
Mysql使用的是典型的C/S架構。連接器通過典型的TCP握手完成連接。
需要註的是,
如果用戶名和密碼都正確,那麼該連接所擁有的許可權僅僅是連接成功建立時的所讀取到的許可權
這就意味著:當連接已經建立後,我們在對該用戶的許可權進行修改,這些修改要直到該用戶再次建立連接時才會生效。
這聽起來是個不好的設計,因為一旦建立連接,管理員是無法臨時收回許可權的。
索性,MySQL也想到了這一點,因此對於已經連接的空閑連接,在一定時間後會自動斷開 --- 由參數wait_timeout
控制,預設值是8小時。
我們可以使用
show processlist
查看已有連接是否處於空閑(Sleep)狀態
想要使用示例資料庫詳見此處
我想,應該是為了用戶許可權的“穩定”才有了上面所謂的“不安全”的設計,因此使用DCL語句的時候要更加謹慎才行。
另外需要註意的是,
MySQL在執行過程中臨時使用的記憶體是管理在連接對象中的
這就意味著,當我們連接一次然後不斷通過該連接進行操作時(即使用長連接時),臨時記憶體會不斷積累,直到連接斷開的時候才釋放。但當記憶體占用過大,被系統殺掉(OOM --- Out of memory ),就會表現為MySQL異常關閉/重啟。
為了避免這種狀況我們可以使用兩種規避方式:
- 避免長連接,儘量使用短連接 --- 但建立連接其實是很耗時的
- 使用MySQL5.7或者更高版本,可以通過
mysql_reset_connection
來初始化連接 --- 即在不重建連接的情況下釋放臨時記憶體(它是一個API方法,而不是直接在mysql shell中使用的命令,詳見)
server層
就根據各個層次的名字一樣,顧名思義,我們主要在在server層處理一條SQL語句,而這個過程在MySQL8.0版本後如下所示:
(連接器)>> 分析器 >> 優化器 >> 執行器
-
分析器就是對SQL字元串的拆分與辨析
-
優化器就是“擇優”,即
在表裡有多個索引的時候選擇使用哪個索引、在多表關聯(join)的時候選擇速度最快的join方式,如在進行如下查詢時
select * from t1 join t2 using(Id) where t1.a=10 and t2.b=20;
優化器就會幫助我們選擇是 “先選出t1.a=10的部分再關聯t2” 還是 “先選出t2.b=20的部分再關聯t1”
-
執行器,
開始執行 》 判斷有沒有相關許可權 》使用表定義中的引擎 》 進行掃描執行語句
在8.0之前的版本還有“查詢緩存”的機制,就是將查詢過的結果放在緩存中以期望下次再次執行相同查詢時能快速返回結果。但...哪裡有那麼多相同的查詢呢,更過分的是這裡的相同還要求表要沒有發生改變,且語句的大小寫都要相同。Are you serious ?於是棄之。
存儲引擎
MySQL存儲引擎負責存儲和提取,其架構是插件式,支持(預設)InnoDB等多個存儲引擎。
搜索引擎是針對錶的,在create table 時可以使用engine = xxx來使用指定記憶體引擎。
讓MySQL為我們記錄執行流程