MySQL的SQL執行背後隱藏了什麼

MySQL的基本體系和架構介紹
相信在大部分的程序員在工作中都有接觸過MySQL這款數據庫,在MySQL的官網上邊,你會看到這樣的一段介紹內容:
在這裏插入圖片描述
大致翻譯過來的意思就是說:
MySQL是世界上最受歡迎的開源數據庫。無論您是快速增長的Web資產,技術ISV還是大型企業,MySQL都能經濟高效地幫助您交付高性能,可擴展的數據庫應用程序。
這款開源的數據庫,其源碼在github上邊的地址爲:https://github.com/mysql/mysql-server star還是挺多的。
那麼既然是一款公認好用的開源數據庫,我們是否應該對它進行一個深入的瞭解呢?

下邊我畫了一個大致的MySQL基本架構圖:
在這裏插入圖片描述
客戶端
MySQL的整體結構可以分成2個大模塊,分別是客戶端和服務端。這裏頭說的客戶端是指提供連接MySQL的工具集合,常見的客戶端工具有mysql client,mysqladmin,mysqldump,mysqlcheck,mysqlimport,mysqlshow等等。MySQL數據庫本身提供的連接方式包含有多種,其中最常見的就是基於TCP/IP協議進行連接了。基礎的命令內容爲:

mysql -h [地址] -u [用戶名] -p [密碼]

在安裝完畢了MySQL數據庫之後,我們會發現數據庫自身已經幫我們預先設置了一個名字叫做mysql的數據庫,每次獲取鏈接的時候就會到該庫裏面的User表檢索賬號信息以及相關的權限。

在Linux系統中,有很多進程間通信方式,套接字(Socket)就是其中的一種。但傳統的套接字的用法都是基於TCP/IP協議棧的,需要指定IP地址。如果不同主機上的兩個進程進行通信,當然這樣做沒什麼問題。但是,如果只需要在一臺機器上的兩個不同進程間通信,還要用到IP地址就有點大材小用了。

MySQL數據庫自身是支持UNIX域套接字進行通信的,因此在MySQL的文件目錄下邊會有這麼一份文件:mysql.sock。
這份文件主要是通過Unix域套接字供我們將本地連接數據庫服務器使用。
以前筆者就遇到過sock文件被修改,導致連接數據庫異常的情況,例如mysql的log中出現這種報錯記錄:

Could not create unix socket lock file

如果sock文件丟失的話,可以重新創建一份sock文件進行通信。

MySQL的鏈接分析
關於mysql的鏈接部分,可以先思考一下下邊的這幾個問題:
MySQL的鏈接分類包含有哪些?
其實MySQL的鏈接包含有很多種類型,常見的類型有:
Unix Sockets
TCP/IP
TLE/SSL

在MySQL的鏈接中,主要的分類有長鏈接類型和短連接類型。

短連接
每次客戶端和服務端進行通信的時候,都需要創建鏈接—》進行通信—》關閉連接。這種鏈接的我們將其定義爲短連接,從它的操作來看這種連接的行爲對於資源的浪費和網絡的消耗是最高的。所以通常我們在工作中較少使用。

長鏈接
長鏈接是我們工作中比較常用的類型,客戶端第一次構建連接之後就不會輕易斷開,這樣可以給後邊多次連接的程序應用所使用,這種設計的好處在於能夠減少資源的損耗,相對於短連接來說要高效些。長鏈接通常都會被設計存儲在連接池裏面,從而減少連接創建的開銷。如果在工作中遇到了一些併發請求比較高的業務場景,光是單單通過配置連接池的方式還是不夠的,還需要有經驗的開發人員在業務層進行相應的隔離。
對於一些訪問量比較低的應用其實可以不使用到連接池這種較重的組件,有可能大量的長鏈接建立了之後都處於sleep狀態,這樣對於內存資源的佔用會比較高。

服務端
每次客戶端想要鏈接到服務端都需要從服務端的連接池獲取相應的連接。假設我們每次連接都需要完成 構建鏈接,當我們獲取到了鏈接之後,在mysql的server端可以通過這樣一個命令來對每個鏈接的狀態進行查看:

mysql> show processList;
+----+-------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+
| Id | User        | Host      | db   | Command | Time   | State                                                  | Info             |
+----+-------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+
|  2 | system user |           | NULL | Connect | 195290 | Waiting for master to send event                       | NULL             |
|  3 | system user |           | NULL | Connect |    257 | Slave has read all relay log; waiting for more updates | NULL             |
| 19 | root        | localhost | NULL | Query   |      0 | starting                                               | show processList |
+----+-------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+
3 rows in set (0.01 sec)

除了上邊的這種情況之外,如果當連接數較多的時候,希望能夠清晰查看到連接的信息可以通過下邊這條指令來操作:

show status like 'Threads%';
結果內容:
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_cached    | 213   |  當前被緩存的空閒線程的數量
| Threads_connected | 191    | 正在使用(處於連接狀態)的線程
| Threads_created   | 409   |  服務啓動以來,創建了多少個線程
| Threads_running   | 5     |  正在忙的線程(正在查詢數據,傳輸數據等等操作)
+-------------------+-------+

查詢緩存
對於一些數據修改變動比較少的表,MySQL內部提供了一套叫做Query Cache的緩存池來進行存儲。MySQL可以通過以下命令來查看內部的查詢緩存參數值:

mysql> show variables like '%query_cache%';
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| have_query_cache             | YES     |
| query_cache_limit            | 1048576 |
| query_cache_min_res_unit     | 4096    |
| query_cache_size             | 1048576 |
| query_cache_type             | OFF     |
| query_cache_wlock_invalidate | OFF     |
+------------------------------+---------+
6 rows in set (0.00 sec)

關於查詢緩存的功能,在MySQL中是根據sql語句來做緩存檢索的,默認情況下該緩存屬性是關閉的,對於更新頻率較高的表而言,設置查詢緩存其實本身的命中率並不高,因此該功能MySQL也並不提倡使用,在MySQL8.0的時候該功能也被移除了。MySQL服務器團隊有一篇關於此的詳細文章有所提及到移除的原因,具體地址如下:
https://mysqlserverteam.com/mysql-8-0-retiring-support-for-the-query-cache/

語法分析器
接下來便是語法分析環節了,該模塊主要是對傳入的SQL語句內容做一些語法內容的校驗,例如判斷該語句是屬於DQL還是DML等類型。其實我個人覺得MySQL裏面最爲複雜的部分就是SQL的語法樹生產的部分,對於這部分的生成需要對編譯器的原理有一定的瞭解,我個人的功力不是很足,所以這裏借用了美團一朋友之前分享給我的圖片來大概演示:
在這裏插入圖片描述

優化器
有時候你會發現,執行的一條SQL可能並不會按照預期的方式來走索引,這是因爲MySQL內部有優化器這麼一個角色的存在。當然索引的選擇只是優化器的其中一項特點,優化器的目的就是通過一定的邏輯判斷,將sql執行的效率發揮到最高效化。

執行器
當Sql準備好了,優化結束了,執行器便會發起sql請求引擎層的接口,這個環節中,執行器還回去判斷當前請求的會話是否有權限執行相關的SQL語句。

存儲引擎
可以說整個數據庫的核心部分就是存儲引擎環節了,不同的存儲引擎對數據的存儲結構和算法設計方便都有着巨大的差別,而且不同的存儲引擎專門爲不同的應用場景所設計。目前我們主流的存儲引擎有Innodb,MyISAM,Memory,等
通過下邊的這條命令我們可以看到MySQL數據庫所支持的存儲引擎有哪些:

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)

關於MySQL的整體架構介紹大概到這裏就先暫時告一段落了,下一篇文章我會講解一些關於存儲引擎的比對問題。

發佈了130 篇原創文章 · 獲贊 34 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章