MySQL快取,SQL語句執行過程

2021-10-21 03:19:51 字數 3154 閱讀 6568

在分析之前我會先帶著你看看 mysql 的基礎架構,知道了 mysql 由那些元件組成已經這些元件的作用是什麼,可以幫助我們理解和解決這些問題。

下圖是 mysql 的乙個簡要架構圖,從下圖你可以很清晰的看到使用者的 sql 語句在 mysql 內部是如何執行的。

先簡單介紹一下下圖涉及的一些元件的基本作用幫助大家理解這幅圖,在 1.2 節中會詳細介紹到這些元件的作用。

查詢快取:執行查詢語句的時候,會先查詢快取(mysql 8.0 版本後移除,因為這個功能不太實用)。

分析器:沒有命中快取的話,sql 語句就會經過分析器,分析器說白了就是要先看你的 sql 語句要幹嘛,再檢查你的 sql 語句語法是否正確。

優化器:按照 mysql 認為最優的方案去執行。

執行器:執行語句,然後從儲存引擎返回資料。

簡單來說 mysql 主要分為 server 層和儲存引擎層:

1) 聯結器

聯結器主要和身份認證和許可權相關的功能相關,就好比乙個級別很高的門衛一樣。

主要負責使用者登入資料庫,進行使用者的身份認證,包括校驗賬戶密碼,許可權等操作,如果使用者賬戶密碼已通過,聯結器會到許可權表中查詢該使用者的所有許可權,之後在這個連線裡的許可權邏輯判斷都是會依賴此時讀取到的許可權資料,也就是說,後續只要這個連線不斷開,即時管理員修改了該使用者的許可權,該使用者也是不受影響的。

2) 查詢快取(mysql 8.0 版本後移除)

查詢快取主要用來快取我們所執行的 select 語句以及該語句的結果集。

連線建立後,執行查詢語句的時候,會先查詢快取,mysql 會先校驗這個 sql 是否執行過,以 key-value 的形式快取在記憶體中,key 是查詢預計,value 是結果集。如果 快取 key 被命中,就會直接返回給客戶端,如果沒有命中,就會執行後續的操作,完成後也會把結果快取起來,方便下一次呼叫。當然在真正執行快取查詢的時候還是會校驗使用者的許可權,是否有該錶的查詢條件。

mysql 查詢不建議使用快取,因為查詢快取失效在實際業務場景中可能會非常頻繁,假如你對乙個表更新的話,這個表上的所有的查詢快取都會被清空。對於不經常更新的資料來說,使用快取還是可以的。

所以,一般在大多數情況下我們都是不推薦去使用查詢快取的。

mysql 8.0 版本後刪除了快取的功能,官方也是認為該功能在實際的應用場景比較少,所以乾脆直接刪掉了。

3) 分析器

mysql 沒有命中快取,那麼就會進入分析器,分析器主要是用來分析 sql 語句是來幹嘛的,分析器也會分為幾步:

第一步,詞法分析,一條 sql 語句有多個字串組成,首先要提取關鍵字,比如 select,提出查詢的表,提出欄位名,提出查詢條件等等。做完這些操作後,就會進入第二步。

第二步,語法分析,主要就是判斷你輸入的 sql 是否正確,是否符合 mysql 的語法。

完成這 2 步之後,mysql 就準備開始執行了,但是如何執行,怎麼執行是最好的結果呢?這個時候就需要優化器上場了。

4) 優化器

優化器的作用就是它認為的最優的執行方案去執行(有時候可能也不是最優,這篇文章涉及對這部分知識的深入講解),比如多個索引的時候該如何選擇索引,多表查詢的時候如何選擇關聯順序等。

可以說,經過了優化器之後可以說這個語句具體該如何執行就已經定下來。

5) 執行器

當選擇了執行方案後,mysql 就準備開始執行了,首先執行前會校驗該使用者有沒有許可權,如果沒有許可權,就會返回錯誤資訊,如果有許可權,就會去呼叫引擎的介面,返回介面執行的結果。

說了以上這麼多,那麼究竟一條 sql 語句是如何執行的呢?其實我們的 sql 可以分為兩種,一種是查詢,一種是更新(增加,更新,刪除)。我們先分析下查詢語句,語句如下:

select

*from tb_student a where a.age=

'18'

and a.name=

' 張三 '

;

結合上面的說明,我們分析下這個語句的執行流程:

以上就是一條查詢 sql 的執行流程,那麼接下來我們看看一條更新語句如何執行的呢?sql 語句如下:

update tb_student a set a.age=

'19'

where a.name=

' 張三 '

;

我們來給張三修改下年齡,在實際資料庫肯定不會設定年齡這個欄位的,不然要被技術負責人打的。其實條語句也基本上會沿著上乙個查詢的流程走,只不過執行更新的時候肯定要記錄日誌啦,這就會引入日誌模組了,mysql 自帶的日誌模組式binlog(歸檔日誌),所有的儲存引擎都可以使用,我們常用的 innodb 引擎還自帶了乙個日誌模組redo log(重做日誌),我們就以 innodb 模式下來**這個語句的執行流程。流程如下:

這裡肯定有同學會問,為什麼要用兩個日誌模組,用乙個日誌模組不行嗎?

這是因為最開始 mysql 並沒與 innodb 引擎( innodb 引擎是其他公司以外掛程式形式插入 mysql 的) ,mysql 自帶的引擎是 myisam,但是我們知道 redo log 是 innodb 引擎特有的,其他儲存引擎都沒有,這就導致會沒有 crash-safe 的能力(crash-safe 的能力即使資料庫發生異常重啟,之前提交的記錄都不會丟失),binlog 日誌只能用來歸檔。

並不是說只用乙個日誌模組不可以,只是 innodb 引擎就是通過 redo log 來支援事務的。那麼,又會有同學問,我用兩個日誌模組,但是不要這麼複雜行不行,為什麼 redo log 要引入 prepare 預提交狀態?這裡我們用反證法來說明下為什麼要這麼做?

如果採用 redo log 兩階段提交的方式就不一樣了,寫完 binglog 後,然後再提交 redo log 就會防止出現上述的問題,從而保證了資料的一致性。那麼問題來了,有沒有乙個極端的情況呢?假設 redo log 處於預提交狀態,binglog 也已經寫完了,這個時候發生了異常重啟會怎麼樣呢?

這個就要依賴於 mysql 的處理機制了,mysql 的處理過程如下:

這樣就解決了資料一致性的問題。

檢視MYSQL已經執行過的sql語句

編輯 etc my.cnf檔案,在 mysqld 節下面新增 log tmp sql row.log行 或者其他路徑,有時因為檔案許可權問題,可能記錄不下來 修改完畢後,記得重啟 mysql service mysql restart 或者 etc init.d mysqld stop etc in...

MySQL監控全部執行過的sql語句

檢視是否開啟日誌記錄 show variables like general log variable name value general log off general log file data0 logs mysql general.log off 關閉 on 開啟 臨時開啟日誌記錄 set...

MySQL監控全部執行過的sql語句

先登入mysql 檢視是否開啟日誌記錄 off 關閉 on 開啟 臨時開啟日誌記錄 set global general log on 這時執行的所有sql都會被記錄下來,但是如果重啟mysql就會停止記錄需要重新設定 mysql exit檢視100行日誌 tail 100f data mysql ...