MySQL之基礎架構

thinkabel發表於2021-01-29

圖片

一、背景

為什麼我先學習MySQL的基礎架構呢? 原因很簡單, 當我們需要了解一項新事物的時候, 我們只有站在巨集觀的層面, 才能層層的去理解問題, 舉個例子, 我們要看一個框架的原始碼, 一開始鑽研進去研究, 發現就有點 “丈二的和尚摸不著頭腦”。因為我們沒有自己的瞭解他,不知道他的入口在哪?

看一個事兒千萬不要直接陷入細節裡,你應該先鳥瞰其全貌,這樣能夠幫助你從高維度理解問題

<MySQL​ 45 講>

二、MySQL 基本架構

圖片

(MySQL 邏輯架構圖)

從圖中我們可以清晰的看到, SQL 語句在MySQL的各個功能模組中的執行過程, 總結一下可以分為 Server 層 和 儲存引擎 兩個部分。

  1. Server層

    Server層包括聯結器、查詢快取、分析器、優化器、執行器等,涵蓋了 MySQL 的大多數核心服務功能, 以及所有的內建函式 (如 時間, 日期, 數學函式 等), 所有跨儲存引擎的功能都在這實現, 儲存過程, 檢視, 觸發器等.

  2. 儲存引擎

    儲存引擎負責資料的儲存和提取。架構模式是外掛式的,支援InnoDB, MyISAM, Memory等 多個儲存引擎. MySQL 5.5.5 版本開始, InnoDB 成為預設儲存引擎。

聯結器

  • 功能作用:負責跟客戶端建立連線、獲取許可權、維持和管理連線,如使用者名稱密碼認證通過,聯結器會到許可權表裡面查出你擁有的許可權。之後,這個連線裡面的許可權判斷邏輯,都將依賴於此時讀到的許可權。修改完成後,只有再新建的連線才會使用新的許可權設定

  • 連線物件:MySQL 在執行過程中臨時使用的記憶體是管理在連線物件裡面的,這些資源會在連線斷開的時候才釋放。

  • 注意點:

  • 在使用者成功連線後,即使你用管理員賬號對該使用者進行了許可權更改,也不會影響已經存在連線的許可權。如果想要許可權生效,只有在新建的連線才會使用新的許可權設定。

在這裡我們要了解兩個點:長連線和短連線的概念。

資料庫裡面,長連線是指連線成功後,如果客戶端持續有請求,則一直使用同一個連線。短連線則是指每次執行完很少的幾次查詢就斷開連線,下次查詢再重新建立一個。

長連結在資料庫中,每次建立連線是比較複雜的,所以在使用中儘量減少建立連線的動作,就是使用長連結。

  • 長連線引發的思考:

  • 風險問題:MySQL在執行過程中臨時使用的記憶體是管理在連線裡面的, 這些資源只有斷開的時候才會釋放, 長連線累積下來,可能會導致記憶體佔用過大,被系統強行殺掉(OOM)

  • 解決方案:定期斷開長連結,使用一段時間,或者執行一個佔用記憶體大的查詢後,斷開連線,在進行重連。如果使用的是MySQL5.7或者更新的版本, 在每次執行比較大的操作後,通過 mysql_reset_connection**重新初始化連線資源**, 這個過程中不需要重連和進行許可權驗證的,但是會恢復到剛剛建立的狀態。

查詢快取

  • 儲存方式:是以** key-value**的形式進行快取在記憶體中的,key 是查詢的語句,value 是查詢的結果。如果你的查詢能夠直接在這個快取中找到 key,那麼這個 value 就會被直接返回給客戶端。

  • 風險:大多數情況下我會建議你不要使用查詢快取,為什麼呢?因為查詢快取往往弊大於利。查詢快取的失效非常頻繁,只要有對一個表的更新,這個表上所有的查詢快取都會被清空。MySQL 8.0 版本直接將查詢快取的整塊功能刪掉了,也就是說 8.0 開始徹底沒有這個功能了。

分析器

  • 詞法分析:識別出 SQL 語句裡面的字串分別是什麼,代表什麼,把** SQL** 語句中字串 T *識別成“表名 *T,把字串** ID** 識別成 列ID

  • 語法分析:根據詞法分析的結果,語法分析器會根據語法規則,判斷你輸入的這個 SQL 語句是否滿足 MySQL 語法

優化器

  • 功能作用:優化器是在表裡面有多個索引的時候,決定使用哪個索引;或者在一個語句有多表關聯(join)的時候,決定各個表的連線順序

優化器

  • 查詢語句

    呼叫 InnoDB 引擎介面取這個表的第一行,判斷 ID 值是不是 5,如果不是則跳過,如果是則將這行存在結果集中

    呼叫引擎介面取 下一行,重複相同的判斷邏輯,直到取到這個表的最後一行

    執行器將上述遍歷過程中所有滿足條件的行組成的記錄集作為結果集返回給客戶端

  • 更新語句

    執行器先找引擎取 ID=2 這一行,ID 是主鍵,引擎直接用樹搜尋找到這一行,如果 *ID=2 *這一行所在的資料頁本來就在記憶體中,就直接返回給執行器,否則,需要先從磁碟讀入記憶體,然後再返回。

    執行器拿到引擎給的行資料,把這個值加上** 1,比如原來是 **N,現在就是 N+1,得到新的一行資料,再呼叫引擎介面寫入這行新資料

    引擎將這行新資料更新到記憶體中,同時將這個更新操作記錄到** redo log** 裡面,此時 redo log 處於 prepare 狀態。然後告知執行器執行完成了,隨時可以提交事務

    執行器生成這個操作的 binlog,並把 binlog 寫入磁碟

    執行器呼叫引擎的提交事務介面,引擎把剛剛寫入的 redo log 改成提交(commit)狀態,更新完成

    圖片

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章