mysql中一条SQLupdate语句是如何执行的?redo log 与binlog
mysql> create table T(id int primary key,c int);
mysql> update T set c=c+1 where id=2;
大體流程與查詢流程是一樣的:先是檢查連接權(quán)限,然后經(jīng)過(guò)分析器,知道是更行語(yǔ)句,查詢緩沖遇到更行語(yǔ)句就清空該表的查詢緩存;優(yōu)化器決定使用id這個(gè)索引并生成執(zhí)行計(jì)劃;執(zhí)行器負(fù)責(zé)執(zhí)行,找到這一行,并進(jìn)行更行。
與查詢流程不一樣的是:更新流程還涉及兩個(gè)重要的日志模塊:redo log與binlog(歸檔日志)
………………………………………………………………………………………………………………………………………………
Redo log
一個(gè)店家有兩個(gè)賬本,A一個(gè)記錄了所有的客戶消費(fèi)信息與欠賬信息;
可日常繁忙時(shí),無(wú)法快速定位將客人信息記錄到A中,這時(shí)就需要臨時(shí)有一個(gè)B,隨時(shí)記錄客人消費(fèi)信息;等晚上客人走了,再將B中的信息整理到A中;
B賬本就是redo log
……………………………………………………………………………………………………………………………………………………
Mysql里也有這個(gè)問(wèn)題,如果每一次的更行操作都需要寫(xiě)入磁盤(pán),然后磁盤(pán)也要找到對(duì)應(yīng)的那條記錄,然后再更行,整個(gè)過(guò)程IO成本,查找成本會(huì)很高。
Mysql就找到一種解決方法:就是WAL技術(shù):先寫(xiě)日志,再寫(xiě)磁盤(pán)。
具體來(lái)說(shuō):當(dāng)有一條記錄需要更新的時(shí)候,INNODB引擎就會(huì)把記錄寫(xiě)到redo log,并更行內(nèi)存,這個(gè)時(shí)候更新就算完成了;同時(shí),innodb引擎會(huì)在適當(dāng)?shù)臅r(shí)候,將這個(gè)操作記錄更新到磁盤(pán)里面。
……………………………………………………………………………………………………………………………………
店鋪掌柜,發(fā)現(xiàn)B賬本快寫(xiě)滿了,那么他就會(huì)將已經(jīng)寫(xiě)進(jìn)A賬本的記錄擦掉,就有了剩余空間,繼續(xù)往里面寫(xiě)記錄
……………………………………………………………………………………………………………………………………
write pos 是當(dāng)前記錄的位置,一邊寫(xiě)一邊后移,寫(xiě)到第 3 號(hào)文件末尾后就回到 0 號(hào)文件開(kāi)頭。checkpoint 是當(dāng)前要擦除的位置,也是往后推移并且循環(huán)的,擦除記錄前要把記錄更新到數(shù)據(jù)文件。
如果wiite pos 追上了checkpoint,表示redo已經(jīng)滿了,不能繼續(xù)執(zhí)行更行操作了,要停下來(lái),等checkpoint向前推移,有了剩余空間,再繼續(xù)更新
…………………………………………………………………………………………………………………………………………
有了redo log,innodb就可以保證數(shù)據(jù)庫(kù)發(fā)生異常重啟后,之前提交的記錄都不會(huì)丟失,這個(gè)能力稱為crash-safe
Redolog 不是記錄數(shù)據(jù)頁(yè)“更改之后的狀態(tài)”,而是記住“頁(yè)做了什么改動(dòng)”
Binlog有兩種模式,statement格式記錄sql語(yǔ)句;row格式記錄行內(nèi)容:更行前后都有
一般選用row模式,因?yàn)橛龅街鲝牟灰恢聲r(shí),row模式,更改前后都有,恢復(fù)之后,不會(huì)丟失某個(gè)事務(wù)的數(shù)據(jù)。
兩種日志的不同:
這兩種日志有以下三點(diǎn)不同。
1 redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 層實(shí)現(xiàn)的,所有引擎都可以使用。
2 redo log 是物理日志,記錄的是“在某個(gè)數(shù)據(jù)頁(yè)上做了什么修改”;binlog 是邏輯日志,記錄的是這個(gè)語(yǔ)句的原始邏輯,比如“給 ID=2 這一行的 c 字段加 1 ”。
3 redo log 是循環(huán)寫(xiě)的,空間固定會(huì)用完;binlog 是可以追加寫(xiě)入的。“追加寫(xiě)”是指 binlog 文件寫(xiě)到一定大小后會(huì)切換到下一個(gè),并不會(huì)覆蓋以前的日志。
……………………………………………………………………………………………………………………………………………………
Binlog或redolog可以二選一嗎?
首先,redo log只有innodb引擎才有,所以不能丟;redo log不具備歸檔的功能,刷到磁盤(pán)后就被清除了;而binlog是追加,可以歸檔,用作數(shù)據(jù)庫(kù)恢復(fù),數(shù)據(jù)庫(kù)擴(kuò)容都很重要。
……………………………………………………………………………………………………………………………………………………
執(zhí)行器先找引擎取ID=2,ID是主鍵,引擎通過(guò)索引快速找到ID=2這一行;如果這一行本就在內(nèi)存中,就直接返回給執(zhí)行器;否則需要從磁盤(pán)讀入內(nèi)存,然后再返回。
執(zhí)行器拿到引擎給的行數(shù)據(jù),把這個(gè)值加1,得到新的行數(shù)據(jù),再調(diào)用引擎接口寫(xiě)入這行新數(shù)據(jù)。
引擎將這行數(shù)據(jù)更新到內(nèi)存中,同時(shí)將這個(gè)更行操作記錄到redo log中,此時(shí)redo log處于prepare狀態(tài)。然后告知執(zhí)行器執(zhí)行完成了,隨時(shí)可以提交事務(wù)。
執(zhí)行器生成這個(gè)操作的binlog,并把binlog寫(xiě)入磁盤(pán)。
執(zhí)行器調(diào)用引擎接口,引擎把redo log 改成commit狀態(tài),更新完成。
最后三步看上去有點(diǎn)繞,將redo log寫(xiě)入拆分為兩個(gè)步驟:prepart和commit------兩階段提交。
…………………………………………………………………………………………………………………………………………
內(nèi)容主體來(lái)自林曉斌老師《mysql實(shí)戰(zhàn)45講》
總結(jié)
以上是生活随笔為你收集整理的mysql中一条SQLupdate语句是如何执行的?redo log 与binlog的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql中,一条select语句是如何
- 下一篇: 数据分析导论