MySQL執行背後隱藏了什麼?

MySQL的基本體系和架構介紹
相信在大部分的程序員在工做中都有接觸過MySQL這款數據庫,在MySQL的官網上邊,你會看到這樣的一段介紹內容:mysql

MySQL執行背後隱藏了什麼?

大體翻譯過來的意思就是說:git

MySQL是世界上最受歡迎的開源數據庫。不管您是快速增加的Web資產,技術ISV仍是大型企業,MySQL都能經濟高效地幫助您交付高性能,可擴展的數據庫應用程序。程序員

這款開源的數據庫,其源碼在github上邊的地址爲:https://github.com/mysql/mysql-server star仍是挺多的。github

那麼既然是一款公認好用的開源數據庫,咱們是否應該對它進行一個深刻的瞭解呢?算法

下邊我畫了一個大體的MySQL基本架構圖:sql

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地址就有點大材小用了。markdown

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的語法樹生產的部分,對於這部分的生成須要對編譯器的原理有必定的瞭解,我我的的功力不是很足,因此這裏借用了美團一朋友以前分享給個人圖片來大概演示:

MySQL執行背後隱藏了什麼?
優化器

有時候你會發現,執行的一條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的總體架構介紹大概到這裏就先暫時告一段落了,下一篇文章我會講解一些關於存儲引擎的比對問題。

相關文章
相關標籤/搜索