mysql:一條SQL更新語句是如何執行的

如下一條更新sql:

UPDATE "public"."t_param_config" SET "id"='12', "param_key"='isOpenRedis', "param_value"='0', "param_desc"='是否啓動Redis:0開啓|1關閉', "status"='1' WHERE ("id"='12');

1、首先還是連接器連接數據庫
2、分析器通過詞法和語法解析知道這是一條更新語句
3、優化器決定是否使用索引
4、執行器具體執行。

1、重要的日誌模塊:redo log-物理日誌

1、在mysql中,如果每一次的更新操作都需要寫進磁盤,然後磁盤也要找到對應的那條記錄然後再更新,那麼整個IO成本、查找成本都很高。爲了解決這個問題,mysql的設計者使用到了WAL技術。WAL即全稱是Write-Ahead Logging,該技術的關鍵點就是先寫日誌,再寫磁盤。具體來說,當有一條記錄需要更新的時候,InnoDB引擎就會先把記錄寫到redo log裏面,並更新內存,這個時候更新就算完成了。同時InnoDB引擎會在適當的時候,將這個操作記錄更新到磁盤裏面,而這個更新操作往往是在系統比較空閒的時候做。

2、InnoDB的redo log的固定大小的,比如可以配置爲一組4個文件,每個文件的大小爲1GB,如下圖所示,write pos是當前記錄的位置,一邊寫一邊後移,寫到第3個號文件末尾後就回到0號文件開頭。checkpoint是當前要擦除的位置,也是往後推移並且循環的,擦除記錄前要把記錄更新到數據文件。(這裏的write pos可以理解爲記錄日誌到內存,checkpoint可以理解爲將內存中的數據寫入到磁盤。)
在這裏插入圖片描述

2、重要的日誌模塊:binlog-邏輯日誌

1、binlog是邏輯日誌,記錄的是這個語句的原始邏輯
2、redo log是循環寫的,空間固定會用完;binlog是可以追加寫入的。“追加寫”是指binlog文件寫到一定大小後會切換到下一個,並不會覆蓋以前的日誌。

3、更新流程

1、執行器先找引擎取ID=2這一行。ID是主鍵,引擎直接用樹搜索找到這一行。如果ID=2這一行所在的數據頁本來就在內存中,就直接返回給執行器;否則,需要先從磁盤讀入內存,然後再返回。
2、執行器拿到引擎給的行數據,把這個值加上1,比如原來是N,現在就是N+1,得到新的一行數據,再調用引擎接口寫入這行新數據。
3、引擎將這行新數據更新到內存中,同時將這個更新操作記錄到redo log裏面,此時redo log處於prepare狀態。然後告知執行器執行完成了,隨時可以提交事務。
4、執行器生成這個操作的binlog,並把binlog寫入磁盤。
5、執行器調用引擎的提交事務接口,引擎把剛剛寫入的redo log改成提交(commit)狀態,更新完成。

在這裏插入圖片描述

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