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內容