Mysql角色與日誌初體驗(從查詢更新入手)

前提:
當我們認知一個人的時候,首先要觀察這個人的外在,再去深入瞭解這個人的內涵。對於我們認識學習mysql也是如此,要先明白它的各個角色組成(形象的比喻)。

Mysql三大角色

客戶端:

客戶端主要用來發起對mysql請求 ,比如我們輸入查詢語句,連接mysql server(mysql -uroot -proot)等。

服務端(核心功能):

連接器

定義:主要是用來處理客戶端和服務端之間的連接,權限判斷。可以通過show processlist指令來查看連接的狀態,連接會有一個默認的超時時間,這個時間可以由wait_timeout控制。
分類:
長連接(長時間使用同一個連接,只有客戶端持有請求,優點是穩定,因爲建立連接的過程比較複雜,儘量使用。缺點是容易佔用大量內存。)
解決上述的問題方法主要有兩個:

  1. 定期斷開長連接。
  2. 新版本的mysql可以使用mysql_reset_connection來重新初始化連接資源)

查詢緩存

緩存中以key-value形式來存儲數據,key是sql語句,value是查詢返回的值,不推薦使用,每次mysql更新表的時候,都會把所有緩存數據清除。高版本的mysql已經刪除去掉緩存

分析器

對mysql語句進行詞法語法分析,先把你輸入的語句進行詞法分析,說白了就是拆分各個字段,並識別其中的字段,比如id啥的。完成詞法分析後,就要對輸入的mysql語句進行語法分析。

優化器

優化器的作用主要就是提高查詢的效率,當表裏面有多個索引的時候,優先決定使用那個索引,或者在有關鍵詞join存在的時候,決定表的連接順序

執行器

分析器讓你知道做什麼,優化器讓你知道如何做更快,經過這兩步就可以真正來執行語句了。執行之前需要再次判斷你是不是對這張表有權限,包括查詢緩存的時候也是如此,也要再做一次權限判斷。權限判定Ok的話,就會根據表的引擎定義,來調用相應存儲引擎的接口查詢數據

存儲引擎

現有的存儲引擎包括:InnoDB(默認)、MyISAM 、Memory,可以通過engine = Memory來指定存儲引擎

=======================================================================

Mysql的查詢流程

知道了MySQL的角色組成後,接下來我們來看看mysql的查詢流程

  1. 客戶端向mysql server發起連接請求,經過連接器校驗成功後,就可以向mysql server發送sql請求
  2. 請求首先會查詢緩存,如果緩存中沒有,則經過分析器、優化器、執行器,最後調用到存儲引擎的接口來查詢數據並返回

redo log和binlog

Mysql的更新流程更新流程和查詢流程類似,不一樣的點在於,更新涉及到兩個重要的日誌模塊:redo log(重做日誌)和binlog(歸檔日誌)

  1. redo log(InnoDB日誌,記錄這個頁做了什麼改動) 如果mysql每次都把數據直接寫入磁盤,查詢也是直接查詢磁盤,這樣想想IO效率都很低,所以mysql引進了WAL(Write-Ahead Logging)技術,這個技術說白了就是沒有直接把數據寫進磁盤,而是先把數據寫到日誌中,等悠閒的時候再把日誌中的數據寫入到磁盤中。機制是這樣的,如果今天操作不多,InnoDB引擎就會選擇在空閒的時間將日誌的數據更新到磁盤中。但是操作特別多的話,日誌已經滿了的話,就會把一部分數據先更新到磁盤中瞭解了redo log的作用後,我們再來看redo log的構造。在InnoDB中redo log是固定大小的。其構造就像一個環。其中有兩個重要的類似指針的東西,一個是write pos(記錄當前寫的位置),另外一個是check point(表示要擦除的位置),之兩個會沿着相同的方向旋轉,其中write pos和checkpoint之間空着的位置就是日誌中空閒的位置,write pos追上check point這個時候說明日誌已經寫完了,就需要更新數據到磁盤中。redo log可以防止mysql出現異常的時候,不會丟失記錄,這種能力成爲crash-safe
  2. binlog(server 層日誌,兩種模式:1、statement模式:記錄sql語句 2、row格式:記錄行的內容)這個日誌是以前在mysql的存引擎還是MysISAM的時候用的,這個日誌並沒有crash-safe的能力,它只能由來歸檔

binlog日誌 和 redlog日誌的差別

  1. redo log是InnoDB引擎特有的,binlog是mysql server層的,所有引擎都可以使用
  2. redo log是物理日誌,記錄某個數據頁做了什麼修改,binlog是邏輯日誌,記錄這個語句的原始邏輯
  3. redo log是循環寫,空間固定會用完;binlog是可以追加寫入的,追加寫的是binlog寫到一定大小後會切換到下一個,不會覆蓋以前的日誌

更新語句的執行流程

  1. 執行器先根據id找到對應的行,如果這一行在內存中,就在內存中查找,否則需要從磁盤讀入內存,再返回。
  2. 執行器拿到數據後,把值修改,再調用引擎接口寫入數據。
  3. 引擎將這行數據更新到內存中,同時將更新記錄到redo log,此時的redo log處於prepare狀態,然後告知執行器執行完畢,可以提交事務。
  4. 執行器生成這個操作的binlog,並把binlog寫入磁盤。
  5. 執行器調用引擎提交事務的接口,引擎把剛剛寫入的redo log改成commit狀態,更新完成。

ps

這裏把redo log的寫入拆分成兩個步驟(一個是prepare,另外一個是commit)這裏是一個兩階段提交,爲了讓兩份日誌之間的邏輯一致。
一般恢復數據到哪個時候的一個狀態都是用binlog來實現的,這裏兩階段提交就是爲了binlog的日誌和redol log的日誌一樣,恢復數據的時候不會出現問題。
redo log用於保證crash-safe能力,innodb_flush_log_At_trx_commit 這個參數設置爲1,表示每次事務的redo log都直接持久化到磁盤 。sync_binlog參數設置爲1的時候,表示每次事務的binlog都持久化到磁盤。

未完待續。。。。。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章