1. 程式人生 > 其它 >Mysql語句執行流程

Mysql語句執行流程

大體來說,MySQL 可以分為 Server 層和儲存引擎層兩部分。

Server層

主要包括聯結器、查詢快取、分析器、優化器、執行器等,涵蓋 MySQL 的大多數核心服務功能,以及所有的內建函式 (如日期、時間、數學和加密函式等),所有跨儲存引擎的功能都在這一層實現,比如儲存過程、觸發器、檢視等

  • 聯結器:管理連線以及許可權控制
  • 分析器:詞法分析、語法分析
  • 優化器:執行計劃生成索引選擇
  • 執行器:呼叫引擎介面獲取查詢結果

引擎層

儲存引擎層負責資料的儲存和提取。其架構模式是外掛式的,支援 InnoDB、MyISAM、Memory 等多個儲存引擎

讀寫磁碟、資料結構化儲存的實現

1. 聯結器

MySQL是開源的,他有非常多種類的客戶端:navicat,mysql front,jdbc,SQLyog等非常豐富的客戶端

向mysql發起通訊都必須先跟Server端建立通訊連線,而建立連線的工作就是有聯結器完成的

mysql ‐h host[資料庫地址] ‐u root[使用者] ‐p root[密碼] ‐P 3306

連線命令中的 mysql 是客戶端工具,用來跟服務端建立連線。在完成經典的 TCP 握手後,聯結器就要開始認證你的身份, 這個時候用的就是你輸入的使用者名稱和密碼。

一個使用者成功建立連線後,即使你用管理員賬號對這個使用者的許可權做了修改,也不會影響已經存在連線的權 限

常用操作

CREATE USER 'username'@'host' IDENTIFIED BY 'password'; #建立新使用者
grant all privileges on *.* to 'username'@'%'; #賦許可權,%表示所有(host)
flush privileges #重新整理資料庫
update user set password=password(”123456″) where user=’root’;#(設定使用者名稱密碼)
show grants for root@"%"; #檢視當前使用者的許可權
show processlist #展示所有連線的客戶端

客戶端如果長時間不傳送command到Server端,聯結器就會自動將它斷開。這個時間是由引數 wait_timeout 控制的,預設值 是 8 小時。

show global variables like "wait_timeout";  # 檢視超時時間
set global wait_timeout=28800; #設定全域性伺服器關閉非互動連線之前等待活動的秒數
  • 長連線:指連線成功後,如果客戶端持續有請求,則一直使用同一個連線
  • 短連線:每次執行完很少的幾次 查詢就斷開連線,下次查詢再重新建立一個

開發當中我們大多數時候用的都是長連線,把連線放在Pool內進行管理,但是長連線有些時候會導致 MySQL 佔用記憶體漲得特別 快,這是因為 MySQL 在執行過程中臨時使用的記憶體是管理在連線物件裡面的。這些資源會在連線斷開的時候才釋放。所以如 果長連線累積下來,可能導致記憶體佔用太大,被系統強行殺掉(OOM),從現象看就是 MySQL 異常重啟了。怎麼解決這類問題呢?

  • 1、定期斷開長連線。使用一段時間,或者程式裡面判斷執行過一個佔用記憶體的大查詢後,斷開連線,之後要查詢再重連。
  • 2、如果你用的是 MySQL 5.7 或更新版本,可以在每次執行一個比較大的操作後,通過執行 mysql_reset_connection 來重新初始化連線資 源。這個過程不需要重連和重新做許可權驗證,但是會將連線恢復到剛剛建立完時的狀態。

2. 查詢快取

MySQL 拿到一個查詢請求後,會先到查詢快取看看,之前是不是執行過這條語句。之前執行過的語句及其結果可能會以 key-value 對的形式,被直接快取在記憶體中。key 是查詢的語句,value 是查詢的結果.

大多數情況查詢快取就是個雞肋,為什麼呢?

因為查詢快取往往弊大於利。查詢快取的失效非常頻繁,只要有對一個表的更新,這個表上所有的查詢快取都會被清空。 因此很可能你費勁地把結果存起來,還沒使用呢,就被一個更新全清空了。對於更新壓力大的資料庫來說,查詢快取的命中率 會非常低。mysql8.0已經移除了快取個功能

一般建議大家在靜態表裡使用查詢快取,什麼叫靜態表呢?就是一般我們極少更新的表

my.cnf
#query_cache_type有3個值 0代表關閉查詢快取OFF,1代表開啟ON,2(DEMAND)代表當sql語句中有SQL_CACHE 關鍵詞時才快取 
query_cache_type=2

這樣對於預設的 SQL 語句都不使用查詢快取。而對於你確定要使用查詢快取的語句,可以用 SQL_CACHE 顯式指定

select SQL_CACHE * from test where ID=5;
show global variables like "%query_cache_type%"; # 檢視當前mysql例項是否開啟快取機制
show status like'%Qcache%'; //檢視執行的快取資訊

3. 分析器

如果沒有命中查詢快取,就要開始真正執行語句了

詞法分析器分成6個主要步驟完成對sql語句的分析

  • 1、詞法分析
  • 2、語法分析
  • 3、語義分析
  • 4、構造執行樹
  • 5、生成執行計劃
  • 6、計劃的執行

4. 優化器

經過了分析器,MySQL 就知道你要做什麼了。在開始執行之前,還要先經過優化器的處理。

優化器是在表裡面有多個索引的時候,決定使用哪個索引;或者在一個語句有多表關聯(join)的時候,決定各個表的連線 順序

5. 執行器

開始執行的時候,要先判斷一下你對這個表 T 有沒有執行查詢的許可權,如果沒有,就會返回沒有許可權的錯誤,如下所示 (在 工程實現上,如果命中查詢快取,會在查詢快取返回結果的時候,做許可權驗證。查詢也會在優化器之前呼叫 precheck 驗證權 限)。

6. bin-log歸檔

刪庫是不需要跑路的,因為我們的SQL執行時,會將sql語句的執行邏輯記錄在我們的bin-log當中

binlog是Server層實現的二進位制日誌,他會記錄我們的cud操作。Binlog有以下幾個特點:

  • 1、Binlog在MySQL的Server層實現(引擎共用)
  • 2、Binlog為邏輯日誌,記錄的是一條語句的原始邏輯
  • 3、Binlog不限大小,追加寫入,不會覆蓋以前的日誌

配置my.cnf

配置開啟binlog 
log‐bin=/usr/local/mysql/data/binlog/mysql‐bin #注意5.7以及更高版本需要配置本項:server‐id=123454(自定義,保證唯一性); 
#binlog格式,有3種statement,row,mixed
binlog‐format=ROW
#表示每1次執行寫入就與硬碟同步,會影響效能,為0時表示,事務提交時mysql不做刷盤操作,由系統決定
sync‐binlog=1

binlog命令

show variables like '%log_bin%'; # 檢視bin‐log是否開啟
 flush logs; # 會多一個最新的bin‐log日誌
 show master status; #檢視最後一個bin‐log日誌的相關資訊
 reset master;# 清空所有的bin‐log日誌

檢視binlog內容

 /usr/local/mysql/bin/mysqlbinlog ‐‐no‐defaults /usr/local/mysql/data/binlog/mysql‐bin. 000001 檢視binlog內容