首先隧甚,我們先來(lái)看看一次查詢/更新語(yǔ)句流程圖
本文會(huì)將重點(diǎn)放在執(zhí)行器<->存儲(chǔ)引擎之間的交互。
mysql不是每次數(shù)據(jù)更改都立刻寫到磁盤渡冻,而是會(huì)先將修改后的結(jié)果暫存在內(nèi)存中,當(dāng)一段時(shí)間后戚扳,再一次性將多個(gè)修改寫到磁盤上,減少磁盤io成本族吻,同時(shí)提高操作速度帽借。
-
mysql通過(guò)WAL(write-ahead logging)技術(shù)保證事務(wù)
在同一個(gè)事務(wù)中,每當(dāng)數(shù)據(jù)庫(kù)進(jìn)行修改數(shù)據(jù)操作時(shí)超歌,將修改結(jié)果更新到內(nèi)存后砍艾,會(huì)在redo log添加一行記錄記錄“需要在哪個(gè)數(shù)據(jù)頁(yè)上做什么修改”,并將該記錄狀態(tài)置為prepare握础,等到commit提交事務(wù)后辐董,會(huì)將此次事務(wù)中在redo log添加的記錄的狀態(tài)都置為commit狀態(tài),之后將修改落盤時(shí)禀综,會(huì)將redo log中狀態(tài)為commit的記錄的修改都寫入磁盤简烘。過(guò)程如下圖
-
redo log記錄方式
redolog的大小是固定的,在mysql中可以通過(guò)修改配置參數(shù)innodb_log_files_in_group和innodb_log_file_size配置日志文件數(shù)量和每個(gè)日志文件大小定枷,redolog采用循環(huán)寫的方式記錄孤澎,當(dāng)寫到結(jié)尾時(shí),會(huì)回到開(kāi)頭循環(huán)寫日志欠窒。如下圖
write pos表示日志當(dāng)前記錄的位置覆旭,當(dāng)ib_logfile_4寫滿后,會(huì)從ib_logfile_1從頭開(kāi)始記錄岖妄;check point表示將日志記錄的修改寫進(jìn)磁盤型将,完成數(shù)據(jù)落盤,數(shù)據(jù)落盤后checkpoint會(huì)將日志上的相關(guān)記錄擦除掉荐虐,即write pos->checkpoint之間的部分是redo log空著的部分七兜,用于記錄新的記錄,checkpoint->write pos之間是redo log待落盤的數(shù)據(jù)修改記錄福扬。當(dāng)writepos追上checkpoint時(shí)腕铸,得先停下記錄,先推動(dòng)checkpoint向前移動(dòng)铛碑,空出位置記錄新的日志狠裹。
有了redo log,當(dāng)數(shù)據(jù)庫(kù)發(fā)生宕機(jī)重啟后汽烦,可通過(guò)redo log將未落盤的數(shù)據(jù)恢復(fù)涛菠,即保證已經(jīng)提交的事務(wù)記錄不會(huì)丟失。
有了redo log撇吞,為啥還需要binlog呢俗冻?
1、redo log的大小是固定的梢夯,日志上的記錄修改落盤后言疗,日志會(huì)被覆蓋掉,無(wú)法用于數(shù)據(jù)回滾/數(shù)據(jù)恢復(fù)等操作颂砸。
2噪奄、redo log是innodb引擎層實(shí)現(xiàn)的,并不是所有引擎都有人乓。
- 基于以上勤篮,binlog必不可少
1、binlog是server層實(shí)現(xiàn)的色罚,意味著所有引擎都可以使用binlog日志
2碰缔、binlog通過(guò)追加的方式寫入的,可通過(guò)配置參數(shù)max_binlog_size設(shè)置每個(gè)binlog文件的大小戳护,當(dāng)文件大小大于給定值后金抡,日志會(huì)發(fā)生滾動(dòng)瀑焦,之后的日志記錄到新的文件上。
3梗肝、binlog有兩種記錄模式榛瓮,statement格式的話是記sql語(yǔ)句, row格式會(huì)記錄行的內(nèi)容巫击,記兩條禀晓,更新前和更新后都有。
binlog和redo log必須保持一致坝锰,不允許出現(xiàn)binlog有記錄但redolog沒(méi)有的情況粹懒,反之亦然。之前說(shuō)過(guò)在一個(gè)事務(wù)中顷级,redolog有prepare和commit兩種狀態(tài)凫乖,所以,在redolog狀態(tài)為prepare時(shí)記錄binlog可保證兩日志的記錄一致愕把,下圖列出各種情況來(lái)說(shuō)明拣凹。
現(xiàn)在我們?cè)賮?lái)看看整個(gè)完整的流程圖
相關(guān)參數(shù)設(shè)置建議:
1、innodb_flush_log_at_trx_commit:設(shè)置為1恨豁,表示每次事務(wù)的redolog都直接持久化到磁盤(注意是這里指的是redolog日志本身落盤)嚣镜,保證mysql重啟后數(shù)據(jù)不丟失。
2橘蜜、sync_binlog: 設(shè)置為1菊匿,表示每次事務(wù)的binlog都直接持久化到磁盤(注意是這里指的是binlog日志本身落盤),保證mysql重啟后binlog記錄是完整的计福。