咱們仍是從一個表的一條更新語句提及,咱們建立下面一張表:數據庫
create table T(ID int primary key, c int);
若是要將ID=2這一行c的值加1,SQL能夠這麼寫:優化
update T set c=c+1 where ID=2;
前一篇文章介紹過SQL語句基本的執行鏈路,能夠確認的說,查詢語句的那一套流程,更新語句也是一樣會走一遍。在執行語句前要先鏈接數據庫,這是鏈接器的工做。接下來,分析器會經過詞法和語法解析知道這是一條更新語句,優化器決定要使用ID這個索引。而後執行器負責具體執行,找到這一行,而後更新。日誌
與查詢流程不同的是,更新流程還涉及兩個重要的日誌模塊:redo log(重作日誌)和binlog(歸檔日誌)。code
MySQL裏面常常說到的WAL技術的全稱是Write-Ahead Logging,它的關鍵點就是行寫日誌再寫磁盤。具體來講,當有一條記錄須要更新的時候,InnoDB引擎會先把記錄寫到redo log裏面,並更新內存,這個時候更新就算完成了。同時InnoDB引擎會在適當的時候,將這個操做記錄更新到磁盤裏面,而這個更新每每是在系統比較閒的時候作。blog
InnoDB的redo log是固定在小的,好比能夠配置爲一組4個文件,每一個文件的大小是1GB,那麼總共就能夠記錄4GB的操做,如圖所示:索引
從頭開始寫,寫到末尾又回到開頭循環寫,write pos是當前記錄的位置,一邊寫一邊後移,寫到3號文件末尾後就回到0號文件開頭。checkpoint是當前要擦除的位置,擦出記錄前要把記錄更新到數據文件中。若是write pos追上checkpoint,這個時候不能再執行新的更新,得停下來先擦除一些記錄,把checkpoint推動一下。接口
有了redo log,InnoDB就能夠保證即便在數據庫發生異常重啓,以前提交的記錄都不會丟失,這個能力稱爲crash-safe。 進程
MySQL總體來看,其實就兩塊:一塊是Server層,它主要作的是MySQL功能層面的事情;還有一塊就是引擎層,負面存儲相關的具體事宜,上面說到的redo log是InnoDB引擎特有的日誌,而Server層也有本身的日誌,稱爲binlog。事務
爲何會有兩份日誌呢?由於最開始MySQL並無InnoDb引擎,MySQL自帶的引擎是MyISAM,但MyISAM並無crash-safe能力,binlog日誌只能用於歸檔。內存
redo log日誌和binlog日誌有如下3個不一樣點:
那麼執行一個簡單的update語句的內部流程以下:
將redo log的寫入折成了兩個步驟:prepare和commit,這就是「兩階段提交」。
簡單來講,redo log和binlog均可以用於表示事務提交狀態,而兩階段提交就是讓這兩個狀態保持邏輯上的一致。