對於MySQL而言,其實分爲客戶端與服務端。java
服務端,就是MySQL應用,當咱們使用net start mysql命令啓動的服務,其實就是啓動了MySQL的服務端。mysql
客戶端,負責發送請求到服務端並從服務端獲取數據,客戶端能夠有多種形式,能夠是咱們經過mysql -uroot -p1234打開的黑窗口,也能夠是咱們使用的Nativecat、SQLyog等數據庫鏈接工具,甚至咱們的程序,也能夠稱做MySQL的客戶端。sql
而當咱們在mysql窗口或者數據庫鏈接工具中輸入一句sql後,咱們就能夠獲取到想要的數據,這中間MySQL究竟是怎麼工做的呢?數據庫
在咱們執行SQL後,例如一句簡單的select * from user where name = ‘yanger’,客戶端發送請求到服務端,請求到達Server層,會通過鏈接器、查詢緩存、分析器、優化器、執行器等,最終經過存儲引擎從文件系統獲取數據或者插入數據到文件系統。緩存
在客戶端程序發起鏈接的時候,須要攜帶主機信息、用戶名、密碼,服務器程序會對客戶端程序提供的這些信息進行認證,若是認證失敗,服務器程序會拒絕鏈接。服務器
鏈接命令你們都比較熟悉。網絡
mysql -h$ip -P$port -u$user -p
輸完命令以後,須要繼續輸入密碼,密碼也能夠直接跟在 -p 後面,但這樣可能會致使你的密碼泄露,若是你連的是生產服務器,強烈建議你不要這麼作。工具
MySQL採用TCP做爲服務器和客戶端之間的網絡通訊協議,完成 TCP 握手後,鏈接器主要作密碼校驗和權限獲取。優化
若是用戶名或密碼不對,你就會收到一個"Access denied for user"的錯誤3d
若是用戶名密碼認證經過,鏈接器會到權限表裏面查出你擁有的權限。以後,這個鏈接裏面的權限判斷邏輯,都將依賴於此時讀到的權限
MySQL的默認鏈接是8小時,由參數 wait_timeout 控制的,若是超過這個時間不使用,會自動斷開,並在以後的操做中,拋出Lost connection to MySQL server during query的錯誤。
針對於查詢語句,MySQL 拿到一個查詢請求後,會先到查詢緩存看看,以前是否是執行過這條語句,以前執行過的語句及其結果可能會以 key-value 對的形式,被直接緩存在內存中。若是命中緩存,將直接返回結果。若是不在查詢緩存中,就會繼續後面的執行階段。執行完成後,執行結果會被存入查詢緩存中。
針對於更新語句,包含插入刪除語句,MySQL 收到更新請求時,會把查詢緩存中該表相關的緩存數據所有清空。
咱們能夠看到,只要有更新,緩存就會失效,而對於正常的業務,更新實際上是比較頻繁的,也就是說,其實MySQL的查詢緩存命中率並不會很高,因此建議通常不到開啓。
能夠經過設置 query_cache_type 爲 DEMAND 來關閉查詢緩存功能。而事實上,在 MySQL 8.0 版本,更是直接移除了查詢緩存這一個功能。
MySQL 首先須要對SQL語句進行分析,分析過程本質上算是一個編譯過程,涉及詞法解析、語法分析、語義分析等階段,經過分析MySQL知道本身要作什麼。
若是語句不對,就會收到「You have an error in your SQL syntax」的錯誤提醒,通常語法錯誤會提示第一個出現錯誤的位置,因此你要關注的是緊接「use near」的內容。
面對分析器拿到的結果,MySQL會作一些優化處理,例如在表裏面有多個索引的時候,決定使用哪一個索引,或者在一個語句有多表關聯(join)的時候,決定各個表的鏈接順序。
優化的結果就是生成一個執行計劃,這個執行計劃代表了應該使用哪些索引進行查詢,表之間的鏈接順序是啥樣的。咱們可使用EXPLAIN語句來查看某個語句的執行計劃。
這裏\G在命令窗口沒法一行時,能夠豎着展現結果,方便查看。
通過了分析器和優化器,就正式進行執行階段了,不過執行以前,須要作權限驗證,若是權限不足,就會拋出權限的錯誤。其實在查詢緩存的時候,同樣也會進行權限校驗。
若是經過驗證,執行器就打開表繼續執行。打開表的時候,執行器就會根據表的引擎定義,去使用這個引擎提供的接口。
MySQL支持很是多種存儲引擎,經常使用的是InnoDB和MyISAM,MySQL的默認存儲引擎是InnoDB。
假如咱們選擇是InnoDB引擎,對於查詢,那InnoDB 會取這個表的第一行來進行判斷是否是符合要求,符合則存在結果集中,不然繼續進行下一行,直到該表的最後一行。
而後存儲引擎將結果返回給執行器, 執行器拿着結果返回給客戶端,這樣一句SQL就執行完成了。