redo(記錄了事務(wù)的行為梢夯,可以很好的通過(guò)其對(duì)頁(yè)進(jìn)行“重做”操作)
- 包含易失的redo log buffer和持久的redo log file兩部分
- 存于redo log file(重做日志文件中)
- 維護(hù)持久性
- 頁(yè)操作
在一個(gè)事務(wù)中的每一次SQL操作之后都會(huì)寫(xiě)入一個(gè)redo log到buffer中,在最后COMMIT的時(shí)候众旗,必須先將該事務(wù)的所有日志寫(xiě)入到redo log file進(jìn)行持久化(這里的寫(xiě)入是順序?qū)懙模┪旮梗聞?wù)的COMMIT操作完成才算完成。
redo
參數(shù) innodb_flush_log_at_trx_commit 用來(lái)控制重做日志刷新到磁盤(pán)的策略,該參數(shù)有3個(gè)值:0几睛、1和2。
0:表示事務(wù)提交時(shí)不進(jìn)行寫(xiě)redo log file的操作粤攒,這個(gè)操作僅在master thread中完成(master thread每隔1秒進(jìn)行一次fsync操作)所森。
1:默認(rèn)值,表示每次事務(wù)提交時(shí)進(jìn)行寫(xiě)redo log file的操作夯接。
2:表示事務(wù)提交時(shí)將redo log寫(xiě)入文件焕济,不過(guò)僅寫(xiě)入文件系統(tǒng)的緩存中,不進(jìn)行fsync操作盔几。
對(duì)比binlog
binlog為了解決Mysql主從備份而產(chǎn)生
* 內(nèi)部XA:redo log和bin log的數(shù)據(jù)一直性和完整性的保證
* 外部XA:分布式事務(wù)
內(nèi)部XA(二段式提交)晴弃,由于需要遵循WAL原則,binlog的過(guò)程需要嵌入到事務(wù)提交的流程中:
* prepare過(guò)程
* commit過(guò)程
在MySQL數(shù)據(jù)庫(kù)中還有一種二進(jìn)制日志(binlog)逊拍,從表面上來(lái)看它和redo log很相似上鞠,都是記錄了對(duì)數(shù)據(jù)庫(kù)操作的日志,但是芯丧,它們有著非常大的不同芍阎。
- redo log是在MySQL的InnoDB引擎層產(chǎn)生,而binlog則是在MySQL的上層產(chǎn)生缨恒,它不僅針對(duì)InnoDB引擎谴咸,其他任何引擎對(duì)于數(shù)據(jù)庫(kù)的更改都會(huì)產(chǎn)生binlog轮听。
- 兩種日志記錄的內(nèi)容形式不同,binlog是一種邏輯日志岭佳,其記錄的是對(duì)應(yīng)的SQL語(yǔ)句血巍。而redo log則是記錄的物理格式日志,其記錄的是對(duì)于每個(gè)頁(yè)的修改驼唱。
- 兩種日志記錄寫(xiě)入磁盤(pán)的時(shí)間點(diǎn)不同藻茂,binlog只在事務(wù)提交完成后一次性寫(xiě)入,而redo log在上面也說(shuō)了是在事務(wù)進(jìn)行中不斷被寫(xiě)入玫恳,這表現(xiàn)為日志并不是隨事務(wù)提交的順序進(jìn)行寫(xiě)入的辨赐。
undo
- 分為insert undo log(insert,insert只對(duì)本身事務(wù)可見(jiàn)京办,對(duì)其他事務(wù)無(wú)影響)和update undo log(update/delete)
- 存于數(shù)據(jù)庫(kù)中的undo segment(段)中
- 用于回滾
- 用于MVCC(實(shí)現(xiàn)非鎖定讀)掀序,讀取一行記錄時(shí),若已被其他事務(wù)占據(jù)惭婿,則通過(guò)undo讀取之前的版本
- 維護(hù)原子性
- 行操作(回滾行記錄到某個(gè)版本)
undo是邏輯日志不恭,只是將數(shù)據(jù)庫(kù)邏輯的恢復(fù)到執(zhí)行語(yǔ)句或事務(wù)之前。
InnoDB存儲(chǔ)引擎的行結(jié)構(gòu)
InnoDB表數(shù)據(jù)的組織方式為主鍵聚簇索引财饥,二級(jí)索引中采用的是(索引鍵值, 主鍵鍵值)的組合來(lái)唯一確定一條記錄换吧。
InnoDB表數(shù)據(jù)為主鍵聚簇索引,mysql默認(rèn)為每個(gè)索引行添加了4個(gè)隱藏的字段,分別是:
- DB_ROW_ID:InnoDB引擎中一個(gè)表只能有一個(gè)主鍵,用于聚簇索引,如果表沒(méi)有定義主鍵會(huì)選擇第一個(gè)非Null的唯一索引作為主鍵,如果還沒(méi)有,生成一個(gè)隱藏的DB_ROW_ID作為主鍵構(gòu)造聚簇索引。
- DB_TRX_ID:最近更改該行數(shù)據(jù)的事務(wù)ID钥星。
- DB_ROLL_PTR:undo log的指針,用于記錄之前歷史數(shù)據(jù)在undo log中的位置沾瓦。
-
DELETE BIT:索引刪除標(biāo)志,如果DB刪除了一條數(shù)據(jù),是優(yōu)先通知索引將該標(biāo)志位設(shè)置為1,然后通過(guò)(purge)清除線程去異步刪除真實(shí)的數(shù)據(jù)。
簡(jiǎn)化過(guò)程
不需要實(shí)時(shí)以同步的方式刷盤(pán)谦炒,數(shù)據(jù)可以后臺(tái)異步寫(xiě)入磁盤(pán)(根據(jù) innodb_flush_log_at_trx_commit參數(shù)值0,1,2來(lái)決定)
redo log寫(xiě)入磁盤(pán)是順序IO
undo log也寫(xiě)入到redo log中
redo 緩存刷盤(pán)規(guī)則:
- 事務(wù)提交時(shí)
- 當(dāng)log buffer 中一半的內(nèi)存空間已經(jīng)被使用時(shí)
- log checkpoint時(shí)
check point
check point機(jī)制是為了減少實(shí)例恢復(fù)的時(shí)間(如果在某個(gè)時(shí)間點(diǎn)贯莺,臟頁(yè)的數(shù)據(jù)被刷新到了磁盤(pán),系統(tǒng)就把這個(gè)刷新的時(shí)間點(diǎn)記錄到redo log的結(jié)尾位置宁改,在進(jìn)行恢復(fù)數(shù)據(jù)的時(shí)候缕探,checkpoint時(shí)間點(diǎn)之前的數(shù)據(jù)就不需要進(jìn)行恢復(fù)了,可以縮短時(shí)間)
- 緩沖池不夠用時(shí)还蹲,觸發(fā)checkpoint爹耗,將臟頁(yè)刷盤(pán)
- 重做日志不夠用時(shí),刷新磁盤(pán)
臟頁(yè):一般業(yè)務(wù)運(yùn)行過(guò)程中谜喊,當(dāng)業(yè)務(wù)需要對(duì)某張的某行數(shù)據(jù)進(jìn)行修改的時(shí)候潭兽,innodb會(huì)先將該數(shù)據(jù)從磁盤(pán)讀取到緩存中去,然后在緩存中對(duì)這條數(shù)據(jù)進(jìn)行修改锅论,這樣緩存中的數(shù)據(jù)就和磁盤(pán)的數(shù)據(jù)不一致了,這個(gè)時(shí)候緩存中的數(shù)據(jù)就稱(chēng)為dirty page楣号,只有當(dāng)臟頁(yè)統(tǒng)一刷新到磁盤(pán)中才會(huì)是clean page
在COMMIT的時(shí)候最易,InnoDB不會(huì)將dirty data page寫(xiě)盤(pán)怒坯。之所以強(qiáng)調(diào)這個(gè)是因?yàn)椋苋菀鬃屓讼氲皆謇粒峤桓淖兙褪菍⑺袞|西寫(xiě)到一個(gè)持久媒介上剔猿。
其實(shí),commit時(shí)只有l(wèi)og記錄需要寫(xiě)嬉荆。寫(xiě)dirty data page只可能發(fā)生在overflow或checkpoint時(shí)刻归敬,因?yàn)樗鼈兊膬?nèi)容是多余的。