MySQL 物理組成-一條更新語句是如何執(zhí)行的
上一小節(jié),我們介紹了MySQL的日志文件和數(shù)據(jù)文件,相信大家對MySQL的物理組成已經(jīng)有了一個初步認(rèn)識。本小節(jié),我們繼續(xù)深入,來看看一條更新語句在MySQL內(nèi)部是如何執(zhí)行的?以及 binlog(歸檔日志)和redo log(重做日志)在其中所起的重要作用。
1.一條更新語句是如何執(zhí)行的
相比查詢語句的執(zhí)行流程,更新語句的執(zhí)行流程多了兩個重要的日志模塊: binlog(歸檔日志)和redo log(重做日志) 。上一小節(jié),我們介紹了這兩個日志的基本概念,大家可能會有疑問,這兩份日志,到底有啥區(qū)別?為什么會有兩份日志呢?
1.1 binlog和redo log的區(qū)別
- binlog是邏輯日志,記錄某個語句的基本邏輯,即SQL語句;redo log是物理日志,記錄在某個數(shù)據(jù)頁所做的修改;
- binlog是在MySQL的Server層實(shí)現(xiàn),所有的存儲引擎都可以使用binlog這個日志模塊;redo log是InnoDB存儲引擎特有的日志模塊;
- binlog是追加寫,在寫滿或重啟之后,會生成新的binlog文件,之前的日志不會進(jìn)行覆蓋;redo log是循環(huán)寫,空間大小是固定的;
- binlog 是在事務(wù)最終提交前寫入的;redo log是在事務(wù)執(zhí)行過程不斷的寫入;
- binlog可以應(yīng)用于數(shù)據(jù)歸檔、主從搭建等場景;redo log作為異常宕機(jī)或者介質(zhì)故障后的數(shù)據(jù)恢復(fù)使用;
1.2 為什么會有兩份日志
剛開始MySQL自帶的引擎是MyISAM,然而MyISAM并沒有crash-safe的能力,而binlog只能用于數(shù)據(jù)歸檔。InnoDB引擎是另外一家公司開發(fā)的MySQL插件,同時開發(fā)了redo log來實(shí)現(xiàn)crash-safe能力。從5.5.5版本開始,InnoDB成為MySQL的默認(rèn)存儲引擎,也是當(dāng)前最常用的存儲引擎。
**Tips:**crash-safe指數(shù)據(jù)庫發(fā)生故障重啟,之前提交的數(shù)據(jù)不會丟失
1.3 一條更新語句的執(zhí)行流程
update語句將id等于1這一行的value值加1
update a set value=value+1 where id=1;
表a擁有一個字段id和一個字段value
CREATE TABLE `a` (
`id` int(11) DEFAULT NULL,
`value` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
我們來看看這條update語句在MySQL內(nèi)部是如何執(zhí)行的?
- 執(zhí)行器通過引擎找到id=1這一行。如果id=1這一行的數(shù)據(jù)頁在內(nèi)存中,直接返回給執(zhí)行器;如果不在,則要從磁盤讀入內(nèi)存,再返回給執(zhí)行器;
- 執(zhí)行器拿到id=1這一行數(shù)據(jù),把value值加1,產(chǎn)生一行新的數(shù)據(jù),調(diào)用引擎接口寫入這行新的數(shù)據(jù);
- 引擎將新的這行數(shù)據(jù)更新到內(nèi)存中,同時將這個操作記錄到redo log,此時redo log處于prepare狀態(tài);
- 執(zhí)行器生成更新操作的binlog,并寫入磁盤;
- 執(zhí)行器調(diào)用引擎的事務(wù)提交接口,引擎將剛剛寫入的redo log改成commit提交狀態(tài),更新完成。
2.小結(jié)
一條更新語句的執(zhí)行過程,除了要經(jīng)過連接池、查詢緩存、解析器、優(yōu)化器、執(zhí)行器這幾個模塊之外,還涉及到兩個非常重要的日志模塊: binlog(歸檔日志)和redo log(重做日志)。
通過本文的講解,希望您對MySQL的物理組成有更深入的認(rèn)識。