wordpress產(chǎn)品傭金杭州百度整站優(yōu)化服務(wù)
MySQL事務(wù)日志—redo日志
事務(wù)有4種特性: 原子性、一致性、隔離性和持久性。
那么事務(wù)的四種特性到底是基于什么機(jī)制實(shí)現(xiàn)?
- 事務(wù)的原子性、一致性由事務(wù)的 undo 日志
- 事務(wù)的隔離性由鎖機(jī)制和MVCC實(shí)現(xiàn)。
- 事務(wù)的持久性由redo 日志來保證。
兩類日志概述:
- REDO LOG 稱為重做日志,用于保存已提交事務(wù)的頁修改操作, 保證事務(wù)的持久性。
- UNDO LOG 稱為回滾日志, 回滾行記錄到某個特定版本, 用來保證事務(wù)的原子性、一致性。
redo日志作用
背景:在真正訪問頁面之前,需要把在磁盤上的頁緩存到內(nèi)存中的 Buffer Pool之后才可以訪問。所有的變更都必須先更新緩沖池中的數(shù)據(jù),然后緩沖池中的臟頁會以一定的頻率被刷入磁盤(checkPoint機(jī)制 ) ,通過緩沖池來優(yōu)化CPU和磁盤之間的鴻溝, 這樣就可以保證整體的性能不會下降太快。
問題:事務(wù)提交并不會觸發(fā)check point機(jī)制馬上進(jìn)行持久化,所以有可能存在事務(wù)內(nèi)容丟失的情況。
redo日志就是保證事務(wù)提交后的持久化的一種機(jī)制。如果發(fā)生宕機(jī),只需要保證數(shù)據(jù)頁的修改記錄已經(jīng)保存到了在redo log中,之后重啟就就可以通過redo log去重新刷盤,保證了持久化。
為什么不是直接刷盤,而是把內(nèi)存數(shù)據(jù)的修改記錄到redo日志里?redo日志不也是磁盤中的嗎?
- 數(shù)據(jù)修改量與刷盤的數(shù)據(jù)量的差距太大,因?yàn)閙ysql是以頁為單位進(jìn)行IO,而修改的數(shù)據(jù)量可能只有幾個字節(jié)。
- 直接刷盤效率太低,因?yàn)镾QL修改的磁盤頁不一定連續(xù),所以說是隨機(jī)IO。
使用redo日志的優(yōu)點(diǎn)?
- 降低了完整刷盤的頻率,每次只記錄頁面修改的內(nèi)容即可
- redo log是順序?qū)懭氪疟P的,屬于順序IO,效率高
redo log什么時候產(chǎn)生?
實(shí)時產(chǎn)生,每執(zhí)行一個SQL語句對應(yīng)的數(shù)據(jù)修改都會記錄在redo log中,而不是事務(wù)提交才記錄。
redo日志工作原理
redo log的組成
Redo log可以簡單分為以下兩個部分:
-
重做日志的緩沖 ( red o log buffer) , 保存在內(nèi)存中, 是易失的。
-
-
重做日志文件 ( redo log file) , 保存在硬盤中, 是持久的。如var/lib/mysql目錄下的ib_logfile0和 ib _logfile1 文件即為REDO日志。
redo log工作流程
InnoDB的更新操作采用的是 Write Ahead Log(預(yù)先日志持久化)策略, 即先寫日志, 再寫入磁盤。
mysql事務(wù)對數(shù)據(jù)進(jìn)行修改,大致過程:
- 開始一個事務(wù)
- 執(zhí)行SQL語句,先將原始數(shù)據(jù)從磁盤中讀入內(nèi)存的buffer pool中來
- 記錄數(shù)據(jù)舊值到undo log以便于回滾,然后再對內(nèi)存中的buffer pool數(shù)據(jù)進(jìn)行修改
- 將內(nèi)存頁的修改情況記錄到redo log buffer(內(nèi)存中)
- 如果事務(wù)中途失敗,則通過undo log回滾
- commit事務(wù),根據(jù)刷盤策略的配置決定采取什么行為,默認(rèn):把redo buffer數(shù)據(jù)直接追加到redo磁盤文件中
- 按照一定頻率執(zhí)行真正的刷盤(check point機(jī)制)
- 如果事務(wù)成功commit但沒有成功刷盤的時候(步驟5-6之間),發(fā)生宕機(jī),則重啟后會根據(jù)redo日志中的記錄再執(zhí)行刷盤
redo日志刷盤策略
redo log刷盤策略是指將redo buffer同步到redo log磁盤文件中的過程
注意:redo log buffer刷盤到 redo log file的過程并不是真正的刷到磁盤中去, 只是刷入到文件系統(tǒng)緩征 ( page cache) 中去 , 真正的寫入會交給系統(tǒng)自己來決定。那么對于InnoDB來說就存在一個問題, 如果交給系統(tǒng)來同步, 同樣如果系統(tǒng)宕機(jī),那么數(shù)據(jù)也丟失了 (雖然整個系統(tǒng)宕機(jī)的概率還是比較小的) 。
針對這種情況, InnoDB給出 innodb _ flush _ log _ at _ trx _ commit參數(shù), 該參數(shù)控制 commit提交事務(wù)時, 如何將 redo log buffer中的日志刷新到 red o log file中。它支持三種策略:
- 設(shè)置為0: 表示每次事務(wù)提交時不進(jìn)行刷盤操作。(系統(tǒng)默認(rèn) master thread每隔1s進(jìn)行一次重做日志的同步)
- 設(shè)置為1 : 表示每次事務(wù)提交時都將進(jìn)行同步, 刷盤操作 (默認(rèn)值)
- 設(shè)置為2: 表示每次事務(wù)提交時都只把 red o log buffer 內(nèi)容寫入 page cache, 不進(jìn)行同步。由 os自己決定什么時候同步到磁盤文件。(其實(shí)也是交給master thread處理)
拓展:master thread是InnoDB存儲引擎的后臺線程, 每隔1 秒, 就會把 redo log buffer 中的內(nèi)容寫到文件系統(tǒng)緩存( page cache) , 然后調(diào)用刷盤操作。三種刷盤策略都會收到master thread的影響。
策略一:事務(wù)提交,立馬同步到redo log文件
優(yōu)點(diǎn):安全性很高,只要事務(wù)提交了,數(shù)據(jù)就是安全的
缺點(diǎn):速度慢
策略二:事務(wù)提交,只保存到文件系統(tǒng)的page cache
優(yōu)點(diǎn):速度快,安全性也相對較高,因?yàn)橹灰研薷挠涗洷4娴絧age cache中了,即使MySQL崩潰了,數(shù)據(jù)也還是能夠保證持久化,除非整個系統(tǒng)宕機(jī)了(概率小)
缺點(diǎn):有概率產(chǎn)生事務(wù)數(shù)據(jù)丟失的情況,丟失1s的數(shù)據(jù)(等待master thread同步的1s的過程中宕機(jī)了)
策略三:事務(wù)提交,什么也不干
優(yōu)點(diǎn):速度快
缺點(diǎn):安全性差,1s內(nèi)發(fā)生MySQL奔潰或者OS宕機(jī),都會丟失事務(wù)的修改數(shù)據(jù)
總結(jié)
redo buffer是實(shí)時變化的,而刷盤不是實(shí)時進(jìn)行的,根據(jù)同步時機(jī),可分為如下三種:
- 事務(wù)commit時,將redo buffer同步到操作系統(tǒng)的文件緩存cache中,然后馬上將文件緩存cache同步寫入到redo log文件中(默認(rèn),做兩步)
- 事務(wù)commit時,只將redo buffer同步到操作系統(tǒng)的文件緩存cache中,具體什么時候同步到redo log文件中,取決于后臺子線程(做一步,另一步交給后臺線程)
- 事務(wù)commit時,什么也不做,什么時候同步完全取決于后臺子線程(什么都不做,都交給后臺線程)
三種策略的安全性由高到低,速度由慢到快,但出于安全考慮,最好還是選擇默認(rèn)的。