臥槽!深度剖析,原來大名鼎鼎的MySQL是這樣執行的!

2022-02-07 菜鳥學Python
mysql在我們的開發中基本每天都要面對的,作為開發中的數據的來源,mysql承擔者存儲數據和讀寫數據的職責。因為學習和了解mysql是至關重要的,那麼當我們在客戶端發起一個sql到出現詳細的查詢數據,這其中究竟經歷了什麼樣的過程?mysql服務端是如何處理請求的,又是如何執行sql語句的?本篇博客將來探討這個問題:

 一:mysql執行過程

mysql整體的執行過程如下圖所示:

 1.1:連接器

連接器的主要職責就是:

①負責與客戶端的通信,是半雙工模式,這就意味著某一固定時刻只能由客戶端向伺服器請求或者伺服器向客戶端發送數據,而不能同時進行,其中mysql在與客戶端連接TC/IP的②驗證請求用戶的帳戶和密碼是否正確,如果帳戶和密碼錯誤,會報錯:Access denied for user 'root'@'localhost' (using password: YES)

③如果用戶的帳戶和密碼驗證通過,會在mysql自帶的權限表中查詢當前用戶的權限:

mysql中存在4個控制權限的表,分別為user表,db表,tables_priv表,columns_priv表,mysql權限表的驗證過程為:1:User表:存放用戶帳戶信息以及全局級別(所有資料庫)權限,決定了來自哪些主機的哪些用戶可以訪問資料庫實例
    Db表:存放資料庫級別的權限,決定了來自哪些主機的哪些用戶可以訪問此資料庫 
    Tables_priv表:存放表級別的權限,決定了來自哪些主機的哪些用戶可以訪問資料庫的這個表 
    Columns_priv表:存放列級別的權限,決定了來自哪些主機的哪些用戶可以訪問資料庫表的這個欄位 
    Procs_priv表:存放存儲過程和函數級別的權限2:先從user表中的Host,User,Password這3個欄位中判斷連接的ip、用戶名、密碼是否存在,存在則通過驗證。3:通過身份認證後,進行權限分配,按照user,db,tables_priv,columns_priv的順序進行驗證。即先檢查全局權限表user,如果user中對應的權限為Y,則此用戶對所有資料庫的權限都為Y,將不再檢查db, tables_priv,columns_priv;如果為N,則到db表中檢查此用戶對應的具體資料庫,並得到db中為Y的權限;如果db中為N,則檢查tables_priv中此資料庫對應的具體表,取得表中的權限Y,以此類推    mysql的緩存主要的作用是為了提升查詢的效率,緩存以key和value的哈希表形式存儲,key是具體的sql語句,value是結果的集合。如果無法命中緩存,就繼續走到分析器的的一步,如果命中緩存就直接返回給客戶端 。不過需要注意的是在mysql的8.0版本以後,緩存被官方刪除掉了。之所以刪除掉,是因為查詢緩存的失效非常頻繁,如果在一個寫多讀少的環境中,緩存會頻繁的新增和失效。對於某些更新壓力大的資料庫來說,查詢緩存的命中率會非常低,mysql為了維護緩存可能會出現一定的伸縮性的問題,目前在5.6的版本中已經默認關閉了,比較推薦的一種做法是將緩存放在客戶端,性能大概會提升5倍左右分析器的主要作用是將客戶端發過來的sql語句進行分析,這將包括預處理與解析過程,在這個階段會解析sql語句的語義,並進行關鍵詞和非關鍵詞進行提取、解析,並組成一個解析樹。具體的關鍵詞包括不限定於以下:select/update/delete/or/in/where/group by/having/count/limit等.如果分析到語法錯誤,會直接給客戶端拋出異常:ERROR:You have an error in your SQL syntax.比如:select *  from user where userId =1234;在分析器中就通過語義規則器將select from where這些關鍵詞提取和匹配出來,mysql會自動判斷關鍵詞和非關鍵詞,將用戶的匹配欄位和自定義語句識別出來。這個階段也會做一些校驗:比如校驗當前資料庫是否存在user表,同時假如User表中不存在userId這個欄位同樣會報錯:unknown column in field list.能夠進入到優化器階段表示sql是符合mysql的標準語義規則的並且可以執行的,此階段主要是進行sql語句的優化,會根據執行計劃進行最優的選擇,匹配合適的索引,選擇最佳的執行方案。比如一個典型的例子是這樣的:表T,對A、B、C列建立聯合索引,在進行查詢的時候,當sql查詢到的結果是:select xx where  B=x and A=x and C=x.很多人會以為是用不到索引的,但其實會用到,雖然索引必須符合最左原則才能使用,但是本質上,優化器會自動將這條sql優化為:where A=x and B=x and C=X,這種優化會為了底層能夠匹配到索引,同時在這個階段是自動按照執行計劃進行預處理,mysql會計算各個執行方法的最佳時間,最終確定一條執行的sql交給最後的執行器 在執行器的階段,此時會調用存儲引擎的API,API會調用存儲引擎,主要有一下存儲的引擎,不過常用的還是myisam和innodb:

 引擎以前的名字叫做:表處理器(其實這個名字我覺得更能表達它存在的意義)負責對具體的數據文件進行操作,對sql的語義比如select或者update進行分析,執行具體的操作。在執行完以後會將具體的操作記錄到binlog中,需要注意的一點是:select不會記錄到binlog中,只有update/delete/insert才會記錄到binlog中。而update會採用兩階段提交的方式,記錄都redolog中可以通過命令:show full processlist,展示所有的處理進程,主要包含了以下的狀態,表示伺服器處理客戶端的狀態,狀態包含了從客戶端發起請求到後臺伺服器處理的過程,包括加鎖的過程、統計存儲引擎的信息,排序數據、搜索中間表、發送數據等。囊括了所有的mysql的所有狀態,其中具體的含義如下圖:

 事實上,sql並不是按照我們的書寫順序來從前往後、左往右依次執行的,它是按照固定的順序解析的,主要的作用就是從上一個階段的執行返回結果來提供給下一階段使用,sql在執行的過程中會有不同的臨時中間表,一般是按照如下順序:

例子: select distinct s.id  from T t join  S s on t.id=s.id where t.name="Yrion" group by t.mobile having count(*)>2  order by s.create_time limit 5;第一步就是選擇出from關鍵詞後面跟的表,這也是sql執行的第一步:表示要從資料庫中執行哪張表。join是表示要關聯的表,on是連接的條件。通過from和join on選擇出需要執行的資料庫表T和S,產生笛卡爾積,生成T和S合併的臨時中間表Temp1。on:確定表的綁定關係,通過on產生臨時中間表Temp2.實例說明:找到表S,生成臨時中間表Temp1,然後找到表T的id和S的id相同的部分組成成表Temp2,Temp2裡面包含著T和Sid相等的所有數據where表示篩選,根據where後面的條件進行過濾,按照指定的欄位的值(如果有and連接符會進行聯合篩選)從臨時中間表Temp2中篩選需要的數據,注意如果在此階段找不到數據,會直接返回客戶端,不會往下進行.這個過程會生成一個臨時中間表Temp3。注意在where中不可以使用聚合函數,聚合函數主要是(min\max\count\sum等函數)實例說明:在temp2臨時表集合中找到T表的name="Yrion"的數據,找到數據後會成臨時中間表Temp3,temp3裡包含name列為"Yrion"的所有表數據group by是進行分組,對where條件過濾後的臨時表Temp3按照固定的欄位進行分組,產生臨時中間表Temp4,這個過程只是數據的順序發生改變,而數據總量不會變化,表中的數據以組的形式存在實例說明:在temp3表數據中對mobile進行分組,查找出mobile一樣的數據,然後放到一起,產生temp4臨時表。對臨時中間表Temp4進行聚合,這裡可以為count等計數,然後產生中間表Temp5,在此階段可以使用select中的別名實例說明:在temp4臨時表中找出條數大於2的數據,如果小於2直接被捨棄掉,然後生成臨時中間表temp5對分組聚合完的表挑選出需要查詢的數據,如果為*會解析為所有數據,此時會產生中間表Temp6實例說明:在此階段就是對temp5臨時聚合表中S表中的id進行篩選產生Temp6,此時temp6就只包含有s表的id列數據,並且name="Yrion",通過mobile分組數量大於2的數據distinct對所有的數據進行去重,此時如果有min、max函數會執行欄位函數計算,然後產生臨時表Temp7實例說明:此階段對temp5中的數據進行去重,引擎API會調用去重函數進行數據的過濾,最終只保留id第一次出現的那條數據,然後產生臨時中間表temp7會根據Temp7進行順序排列或者逆序排列,然後插入臨時中間表Temp8,這個過程比較耗費資源實例說明:這段會將所有temp7臨時表中的數據按照創建時間(create_time)進行排序,這個過程也不會有列或者行損失limit對中間表Temp8進行分頁,產生臨時中間表Temp9,返回給客戶端。實例說明:在temp7中排好序的數據,然後取前五條插入到Temp9這個臨時表中,最終返回給客戶端ps:實際上這個過程也並不是絕對這樣的,中間mysql會有部分的優化以達到最佳的優化效果,比如在select篩選出找到的數據集了解mysql的執行過程,以及sql的執行順序,理解這些有助於我們對sql語句進行優化,以及明白mysql中的sql語句從寫出來到最終執行的軌跡,有助於我們對sql有比較深入和細緻的理解,提高我們的資料庫理解能力。同時,對於複雜sql的執行過程、編寫都會有一定程度的意義。

相關焦點

  • 《MySQL》系列 - select 語句是怎麼執行的?
    事情是這樣的,某天我司小胖問我執行 select * from table,資料庫底層到底發生了啥?從而我們得到數據呢?以下把我給問住了,為此我查閱了大量的書籍、博客。於是就有了這篇文章。mysql 連結資料庫是這樣寫的:mysql -h 127.0.0.1 -P 3306 -u root -p# 127.0.0.1 : ip 3306 : 埠 root : 用戶名運行命令之後需要輸入密碼,當然也可以跟在 -p 後面。
  • MySQL何時執行flush privileges?
    需求背景我們平時在給用戶授權grant語句執行後,都習慣性的執行一個命令flush privileges;,但是我發現有時候不執行這個命令,授權語句執行之後,權限驗證也是OK的,但是有時候發現不執行這個flush privileges;命令,權限認證還不能通過。
  • 技術分享 | MySQL 執行 GROUP BY 的四種方式
    可能負責查詢執行時間 90% 還多。MySQL 執行 GROUP BY 時的主要複雜性是計算 GROUP BY 語句中的聚合函數。UDF 聚合函數是一個接一個地獲得構成單個組的所有值。這樣,它可以在移動到另一個組之前計算單個組的聚合函數值。當然,問題在於,在大多數情況下,源數據值不會被分組。來自各種組的值在處理期間彼此跟隨。因此,我們需要一個特殊的步驟。
  • MySQL-SQL語句執行流程
    你可以將參數 query_cache_type 設置成 DEMAND,這樣對於默認的 SQL 語句都不使用查詢緩存。分析器首先通過mysql關鍵字將語句解析,會生成一個內部解析樹,mysql解析器將對其解析,查看是否是有錯誤的關鍵字,關鍵字順序是佛正確;預處理器則是根據mysql的規則進行進一步的檢查,檢查mysql語句是否合法,如,庫表是否存在,欄位是否存在,欄位之間是否模稜兩可等等,預處理器也會驗證權限。
  • 一條查詢SQL在MySQL中是怎麼執行的
    這樣在我們以後遇到MySQL的一些異常或者問題的時候,就可以快速定位問題並解決問題。下邊通過一張圖來看一下SQL的執行流程,從中可以清楚的看到SQL語句在MySQL的各個功能模塊中執行的過程。從上圖來看,MySQL大體上可以分為Server層和存儲引擎層兩部分。
  • 生產MySQL資料庫執行一次analyze採集信息,應用炸了
    ,發現執行計劃不正確,第一反應就是其中的一個表的統計信息不準確,導致了SQL語句的執行計劃不對,從高效的查詢SQL變成了慢SQL。:模擬執行analyze命令之後,在t_test_1表上執行一次select查詢mysql> select * from t_test_1 where id=5;session4:查詢所有會話信息
  • 2021山東公務員考試申論貫徹執行題深度剖析之「活動方案」
    2021山東公務員考試申論貫徹執行題深度剖析之「活動方案」 2020-11-26 15:46:10| 來源:中公教育 李玲玲 申論考試是山東公務員考試必考科目之一,想要在山東省考申論中取得好成績
  • 資料庫 | 跟郭導學MySQL:索引及執行計劃
    作用: 語句執行前,先看執行計劃信息,可以有效的防止性能較差的語句帶來的性能問題.如果業務中出現了慢語句,我們也需要藉助此命令進行語句的評估,分析優化方案。(2) select 獲取數據的方法1. 全表掃描(應當儘量避免,因為性能低)2. 索引掃描3.
  • 「MySQL系列」分析Sql執行時間及查詢執行計劃(附資料庫和一千萬數據)
    接下來這篇文章我們來看看如何分析我們的sql執行效率。首先找到執行慢的sql,然後對執行慢的SQL進行分析。在分析之前是不是有這樣的困惑,我的數據量這麼少。我如何分析SQL執行效率。不要慌,我們已準備了一千萬條數據。接下來看看如何將這一千萬條數據快速導入到資料庫中。
  • 360 私有雲平臺 MySQL 自動化實現剖析
    HULK 私有雲平臺 MySQL 服務剖析 -- MySQL 自動化在 HULK 中的實現, 這次的分享題目是:HULK 私有雲平臺 MySQL 服務剖析 -- MySQL 自動化在 HULK 中的實現。
  • MySQL 存儲引擎如何完成一條更新語句的執行
    (給數據分析與開發加星標,提升數據技能)來源:月伴飛魚 (本文來自作者投稿)假設我們有一條SQL語句是這樣的
  • MySQL執行計劃及SQL優化策略
    如果將主鍵置於where列表中,mysql就能將該查詢轉換為一個consteq_ref:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或 唯一索引掃描。也就是說mysql無法利用索引完成的排序操作成為「文件排序」Using temporary:使用臨時表保存中間結果,也就是說mysql在對查詢結果排序時使用了臨時表,常見於order by 和 group byUsing index:表示相應的select操作中使用了覆蓋索引
  • 2021年甘肅公務員申論技巧:貫徹執行題深度剖析之「活動方案」
    2021年甘肅公務員申論技巧:貫徹執行題深度剖析之「活動方案」 甘肅省公務員考試筆試內容包括:行政職業能力測試以及申論,對於申論而言,主要是以4道題為主,3道客觀題,1道大作文,掌握的內容在於平時的積累,比如申論熱點
  • PHP技巧:通過實例深入剖析require和include的用法
    首頁 > 語言 > 關鍵詞 > php最新資訊 > 正文 PHP技巧:通過實例深入剖析require和include的用法
  • Mysql中一條SQL查詢語句是如何執行的?
    1.前言在深入學習前我們應該跳出來,從整體的架構上來了解一下MySQL,這樣更有利於我們學習。2.查詢流程解析select * from table1 where ID=10;這條語句相信大家再熟悉不過了,下面我們就看看這一條語句在mysql中是怎麼執行的。第一步:一條sql語句要經過連接器,客戶端要和mysql建立連接。
  • MySQL 架構總覽、從查詢執行流程到SQL 解析順序
    前言一直是想知道一條SQL語句是怎麼被執行的,它執行的順序是怎樣的,然後查看總結各方資料,就有了下面這一篇博文了。本文將從MySQL總體架構--->查詢執行流程--->語句執行順序來探討一下其中的知識。
  • 北京人口中的「臥槽」是啥意思?高曉松:他們打電話全程「臥槽」
    在日常的生活中,我們經常會接觸到北京人,他們一接電話就經常說臥槽,那麼,我們不禁要問臥槽是罵人的嗎? 無意間在刷短視頻的時候看見高曉松與馬未都的一次脫口秀,他們倆就對於北京人說的這個詞展開了討論。
  • 時間精度引起MySQL主從不一致問題剖析
    *;import java.text.SimpleDateFormat;public class insertData {    public static void main(String[] args)    {        String driver = "com.mysql.jdbc.Driver";        String url = "jdbc:mysql://127.0.0.1:
  • MySQL 刪除資料庫 | Mysql Drop Database
    在刪除資料庫過程中,務必要十分謹慎,因為在執行刪除命令後,所有數據將會消失。drop 命令刪除資料庫mysql> drop database RUNOON;使用 mysqladmin 刪除資料庫你也可以使用 mysql mysqladmin 命令在終端來執行刪除命令。
  • MySQL教程之MySQL定時備份資料庫
    /mydb.sql二、 編寫腳本維護備份的資料庫文件在linux中,通常使用BASH腳本對需要執行的內容進行編寫,加上定時執行命令crontab實現日誌自動化生成。2.執行mysqldump命令保存備份文件,並將操作列印至同目錄下的log.txt中標記操作日誌。3.定義需要刪除的文件:通過ls命令獲取第九列,即文件名列,再通過head -1實現定義操作時間最晚的那個需要刪除的文件。