一條更新SQL的內部執行及日誌模組

2022-10-11 09:51:11 字數 3153 閱讀 4043

學習mysql實戰45講,非常推薦學

還是老圖:上文複習

在執行查詢語句的時候,會執行聯結器(總要連上才能搞事情),然後去查詢快取(mysql8+刪除了),有資料返回,沒資料進行分析器-優化器-執行器-執行引擎流程並且其特點是如果該錶上有更新,都會把快取結果清空

update t set c=c+1 where id=2;
流程:聯結器:連線資料庫

分析器:分析詞法和語法解析知道這是更新語句

優化器:決定使用id進行索引

執行器:具體執行,找到改行然後更新

更新對查詢來說,涉及到了兩個重要的日誌模組,redo log(重做日誌)innodb特有的,binlog(歸檔日誌)server中存在的,只要持續學習資料庫方面,這兩個是繞不過的。

在innodb中redo log的大小是固定的,可以配置為一組4個檔案,每個檔案的大小是1gb,那麼這塊redo log總共就可以記錄4gb的操作(可以自己設定)。

mysql中的問題:

如果每一次的更新操作都需要寫進磁碟,然後磁碟也要找到對應的那條記錄,然後再更新,整個過程io成本、查詢成本都很高

解決問題:

wal技術:write-ahead logging

寫日誌寫磁碟

執行流程:

為什麼 redo log 具有 crash-safe 的能力,是 binlog 無法替代的?

redo log的被動刷盤機制

明確定義:

write:刷盤

fsync:持久化到磁碟

write(刷盤)指的是mysql從buffer pool中將內容寫到系統的page cache中,並沒有持久化到系統磁碟上。這個速度其實是很快的。

fsync指的是從系統的cache中將資料持久化到系統磁碟上。這個速度可以認為比較慢,而且也是iops公升高的真正原因。

redo log是物理日誌,記錄的是「在某個資料頁上做了什麼修改」,內部結構是基於頁的,記錄了這個頁的字段值變化,只要crash後讀取redo log進行重放就可以恢復資料。(因為redo log是迴圈寫的,如果滿了innodb就會執行真正寫盤)。

好處是不用每一次操作都實時把資料寫盤,就算crash後也可以通過redo log重放恢復,所以能夠實現快速響應sql語句。

mysql剛開始是使用的自帶引擎myisam,但其沒有crash-safe,binlog日誌只能用於歸檔,5.5版本之後引入innodb,通過redo log來實現crash-safe能力。

redo log與binlog的區別redo log 是 innodb 引擎特有的;binlog 是 mysql 的 server 層實現的,所有引擎都可以使用。

redo log 是物理日誌記錄的是在某個資料頁上做了什麼修改;binlog 是邏輯日誌記錄的是這個語句的原始邏輯,比如「給 id=2 這一行的 c 欄位加 1 」。

redo log 是迴圈寫的,空間固定會用完;binlog 是可以追加寫入的。「追加寫」是指 binlog 檔案寫到一定大小後會切換到下乙個,並不會覆蓋以前的日誌

update內部執行流程:

流程圖:圖中淺色框表示是在 innodb 內部執行的,深色框表示是在執行器中執行的

其中redo log分為兩個階段提交:這是為了讓兩份日誌之間的邏輯一致

redo log prepare階段

commit階段

好處:保證redo log和binlog都能同時失敗或者成功。

如果不採用兩階段提交,那麼redo log和binlog是單獨的邏輯,由此引出下面兩種提交方式:

先寫redo log,後寫binlog

先寫binlog,後寫redo log

還是以update為例:

update t set c=c+1 where id=2;
先寫redo log,後寫binlog在redo log寫完,binlog沒寫完的時候,mysql 程序異常重啟,因為其實先寫入記憶體的,所以mysql崩潰後仍然能把資料恢復

根據備份恢復後c的值為1.但由於binlog沒有寫完就崩潰了,這時候binlog就沒有記錄這條語句的操作,使用binlog恢復的時候就會少一次更新,c的值為0,這就與原庫的值不同了。

先寫binlog,後寫redo log與上面邏輯相同都會造成恢復的資料與原庫值不同;

可以看到,如果不使用「兩階段提交」,那麼資料庫的狀態就有可能和用它的日誌恢復出來的庫的狀態不一致

但是當按照上述流程圖來說,在進行兩階段提交的時候,即a、b時刻出現crash,是怎麼處理的。

流程如下:

b時刻發生crash後對應的是2(a)的情況,崩潰恢復過程中事務會被提交。

由此引出的很多問題,感興趣的朋友可以看下mysql實戰45講答疑篇第一章

備份的流程:

找到最近的一次全量備份,從這個備份恢復到臨時庫;

從備份的時間點開始,將備份的 binlog 依次取出來,重放到中午誤刪表之前的那個時刻。

備份恢復的資料的場景:

誤操作後需要恢復資料

要擴容的時候,也需要再多搭建一些備庫來增加系統的讀能力的時候,用全量備份加上應用binlog 來實現的。如果這個「不一致」就會導致你的線上出現主從資料庫不一致的情況

一條SQL更新語句的執行過程

目錄如果執行這條更新語句資料庫是如何執行的呢?update student set name 小明 where studentid 1根據之前說過的sql語句查詢的流程來說,只要表上有資料更新,有關查詢的索引就會失效,接下來分析器會根據每個單詞識別知道這是update語句,優化器根據這個id獲取需要...

02一條update的sql的內部執行流程

執行器和 innodb 引擎在執行這個簡單的 update 語句時的內部流程。1 執行器先找引擎取 id 2 這一行。id 是主鍵,引擎直接用樹搜尋找到這一行。如果 id 2 這一行所在的資料頁本來就在記憶體中,就直接返回給執行器 否則,需要先從磁碟讀入記憶體,然後再返回。2 執行器拿到引擎給的行資...

日誌系統 一條SQL更新語句是如何執行的

一 重要的日誌模組 redo log wal技術 先寫日誌,再寫磁碟。具體是當有一條紀錄需要更新的時候,innodb引擎就會先把紀錄寫到redo log裡面,並更新記憶體,在引擎空閒的時候,將這個操作紀錄更新到磁碟裡面。1 redo log紀錄了這個資料頁做了什麼改動 2 redo log 是固定大...