共計(jì) 3499 個(gè)字符,預(yù)計(jì)需要花費(fèi) 9 分鐘才能閱讀完成。
這篇文章將為大家詳細(xì)講解有關(guān) mysql 中 undo log 及 redo log 是什么,丸趣 TV 小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
00 – Undo Log
Undo Log 是為了實(shí)現(xiàn)事務(wù)的原子性,在 MySQL 數(shù)據(jù)庫(kù) InnoDB 存儲(chǔ)引擎中,還用 Undo Log 來(lái)實(shí)現(xiàn)多版本并發(fā)控制(簡(jiǎn)稱:MVCC)。
– 事務(wù)的原子性 (Atomicity)
事務(wù)中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作。如果在執(zhí)行的過(guò)程中發(fā)生
了錯(cuò)誤,要回滾(Rollback) 到事務(wù)開始前的狀態(tài),就像這個(gè)事務(wù)從來(lái)沒(méi)有執(zhí)行過(guò)。
– 原理
Undo Log 的原理很簡(jiǎn)單,為了滿足事務(wù)的原子性,在操作任何數(shù)據(jù)之前,首先將數(shù)據(jù)備份到一個(gè)地方
(這個(gè)存儲(chǔ)數(shù)據(jù)備份的地方稱為 Undo Log)。然后進(jìn)行數(shù)據(jù)的修改。如果出現(xiàn)了錯(cuò)誤或者用戶執(zhí)行了
ROLLBACK 語(yǔ)句,系統(tǒng)可以利用 Undo Log 中的備份將數(shù)據(jù)恢復(fù)到事務(wù)開始之前的狀態(tài)。
除了可以保證事務(wù)的原子性,Undo Log 也可以用來(lái)輔助完成事務(wù)的持久化。
– 事務(wù)的持久性(Durability)
事務(wù)一旦完成,該事務(wù)對(duì)數(shù)據(jù)庫(kù)所做的所有修改都會(huì)持久的保存到數(shù)據(jù)庫(kù)中。為了保證持久性,數(shù)據(jù)庫(kù)
系統(tǒng)會(huì)將修改后的數(shù)據(jù)完全的記錄到持久的存儲(chǔ)上。
– 用 Undo Log 實(shí)現(xiàn)原子性和持久化的事務(wù)的簡(jiǎn)化過(guò)程
假設(shè)有 A、B 兩個(gè)數(shù)據(jù),值分別為 1,2。
A. 事務(wù)開始.
B. 記錄 A = 1 到 undo log.
C. 修改 A =3.
D. 記錄 B = 2 到 undo log.
E. 修改 B =4.
F. 將 undo log 寫到磁盤。
G. 將數(shù)據(jù)寫到磁盤。
H. 事務(wù)提交
這里有一個(gè)隱含的前提條件:‘?dāng)?shù)據(jù)都是先讀到內(nèi)存中,然后修改內(nèi)存中的數(shù)據(jù),最后將數(shù)據(jù)寫回磁盤’。
之所以能同時(shí)保證原子性和持久化,是因?yàn)橐韵绿攸c(diǎn):
A. 更新數(shù)據(jù)前記錄 Undo log。
B. 為了保證持久性,必須將數(shù)據(jù)在事務(wù)提交前寫到磁盤。只要事務(wù)成功提交,數(shù)據(jù)必然已經(jīng)持久化。
C. Undo log 必須先于數(shù)據(jù)持久化到磁盤。如果在 G,H 之間系統(tǒng)崩潰,undo log 是完整的,
可以用來(lái)回滾事務(wù)。
D. 如果在 A - F 之間系統(tǒng)崩潰, 因?yàn)閿?shù)據(jù)沒(méi)有持久化到磁盤。所以磁盤上的數(shù)據(jù)還是保持在事務(wù)開始前的狀態(tài)。
缺陷:每個(gè)事務(wù)提交前將數(shù)據(jù)和 Undo Log 寫入磁盤,這樣會(huì)導(dǎo)致大量的磁盤 IO,因此性能很低。
如果能夠?qū)?shù)據(jù)緩存一段時(shí)間,就能減少 IO 提高性能。但是這樣就會(huì)喪失事務(wù)的持久性。因此引入了另外一
種機(jī)制來(lái)實(shí)現(xiàn)持久化,即 Redo Log.
01 – Redo Log
– 原理
和 Undo Log 相反,Redo Log 記錄的是新數(shù)據(jù)的備份。在事務(wù)提交前,只要將 Redo Log 持久化即可,
不需要將數(shù)據(jù)持久化。當(dāng)系統(tǒng)崩潰時(shí),雖然數(shù)據(jù)沒(méi)有持久化,但是 Redo Log 已經(jīng)持久化。系統(tǒng)可以根據(jù)
Redo Log 的內(nèi)容,將所有數(shù)據(jù)恢復(fù)到最新的狀態(tài)。
– Undo + Redo 事務(wù)的簡(jiǎn)化過(guò)程
假設(shè)有 A、B 兩個(gè)數(shù)據(jù),值分別為 1,2.
A. 事務(wù)開始.
B. 記錄 A = 1 到 undo log.
C. 修改 A =3.
D. 記錄 A = 3 到 redo log.
E. 記錄 B = 2 到 undo log.
F. 修改 B =4.
G. 記錄 B = 4 到 redo log.
H. 將 redo log 寫入磁盤。
I. 事務(wù)提交
– Undo + Redo 事務(wù)的特點(diǎn)
A. 為了保證持久性,必須在事務(wù)提交前將 Redo Log 持久化。
B. 數(shù)據(jù)不需要在事務(wù)提交前寫入磁盤,而是緩存在內(nèi)存中。
C. Redo Log 保證事務(wù)的持久性。
D. Undo Log 保證事務(wù)的原子性。
E. 有一個(gè)隱含的特點(diǎn),數(shù)據(jù)必須要晚于 redo log 寫入持久存儲(chǔ)。
– IO 性能
Undo + Redo 的設(shè)計(jì)主要考慮的是提升 IO 性能。雖說(shuō)通過(guò)緩存數(shù)據(jù),減少了寫數(shù)據(jù)的 IO.
但是卻引入了新的 IO,即寫 Redo Log 的 IO。如果 Redo Log 的 IO 性能不好,就不能起到提高性能的目的。
為了保證 Redo Log 能夠有比較好的 IO 性能,InnoDB 的 Redo Log 的設(shè)計(jì)有以下幾個(gè)特點(diǎn):
A. 盡量保持 Redo Log 存儲(chǔ)在一段連續(xù)的空間上。因此在系統(tǒng)第一次啟動(dòng)時(shí)就會(huì)將日志文件的空間完全分配。
以順序追加的方式記錄 Redo Log, 通過(guò)順序 IO 來(lái)改善性能。
B. 批量寫入日志。日志并不是直接寫入文件,而是先寫入 redo log buffer. 當(dāng)需要將日志刷新到磁盤時(shí)
(如事務(wù)提交), 將許多日志一起寫入磁盤.
C. 并發(fā)的事務(wù)共享 Redo Log 的存儲(chǔ)空間,它們的 Redo Log 按語(yǔ)句的執(zhí)行順序,依次交替的記錄在一起,
以減少日志占用的空間。例如,Redo Log 中的記錄內(nèi)容可能是這樣的:
記錄 1: trx1, insert …
記錄 2: trx2, update …
記錄 3: trx1, delete …
記錄 4: trx3, update …
記錄 5: trx2, insert …
D. 因?yàn)?C 的原因, 當(dāng)一個(gè)事務(wù)將 Redo Log 寫入磁盤時(shí),也會(huì)將其他未提交的事務(wù)的日志寫入磁盤。
E. Redo Log 上只進(jìn)行順序追加的操作,當(dāng)一個(gè)事務(wù)需要回滾時(shí),它的 Redo Log 記錄也不會(huì)從
Redo Log 中刪除掉。
02 – 恢復(fù)(Recovery)
– 恢復(fù)策略
前面說(shuō)到未提交的事務(wù)和回滾了的事務(wù)也會(huì)記錄 Redo Log,因此在進(jìn)行恢復(fù)時(shí), 這些事務(wù)要進(jìn)行特殊的
的處理. 有 2 中不同的恢復(fù)策略:
A. 進(jìn)行恢復(fù)時(shí),只重做已經(jīng)提交了的事務(wù)。
B. 進(jìn)行恢復(fù)時(shí),重做所有事務(wù)包括未提交的事務(wù)和回滾了的事務(wù)。然后通過(guò) Undo Log 回滾那些
未提交的事務(wù)。
– InnoDB 存儲(chǔ)引擎的恢復(fù)機(jī)制
MySQL 數(shù)據(jù)庫(kù) InnoDB 存儲(chǔ)引擎使用了 B 策略, InnoDB 存儲(chǔ)引擎中的恢復(fù)機(jī)制有幾個(gè)特點(diǎn):
A. 在重做 Redo Log 時(shí),并不關(guān)心事務(wù)性。恢復(fù)時(shí),沒(méi)有 BEGIN,也沒(méi)有 COMMIT,ROLLBACK 的行為。
也不關(guān)心每個(gè)日志是哪個(gè)事務(wù)的。盡管事務(wù) ID 等事務(wù)相關(guān)的內(nèi)容會(huì)記入 Redo Log,這些內(nèi)容只是被當(dāng)作
要操作的數(shù)據(jù)的一部分。
B. 使用 B 策略就必須要將 Undo Log 持久化,而且必須要在寫 Redo Log 之前將對(duì)應(yīng)的 Undo Log 寫入磁盤。
Undo 和 Redo Log 的這種關(guān)聯(lián),使得持久化變得復(fù)雜起來(lái)。為了降低復(fù)雜度,InnoDB 將 Undo Log 看作
數(shù)據(jù),因此記錄 Undo Log 的操作也會(huì)記錄到 redo log 中。這樣 undo log 就可以象數(shù)據(jù)一樣緩存起來(lái),
而不用在 redo log 之前寫入磁盤了。
包含 Undo Log 操作的 Redo Log,看起來(lái)是這樣的:
記錄 1: trx1, Undo log insert undo_insert …
記錄 2: trx1, insert …
記錄 3: trx2, Undo log insert undo_update …
記錄 4: trx2, update …
記錄 5: trx3, Undo log insert undo_delete …
記錄 6: trx3, delete …
C. 到這里,還有一個(gè)問(wèn)題沒(méi)有弄清楚。既然 Redo 沒(méi)有事務(wù)性,那豈不是會(huì)重新執(zhí)行被回滾了的事務(wù)?
確實(shí)是這樣。同時(shí) Innodb 也會(huì)將事務(wù)回滾時(shí)的操作也記錄到 redo log 中。回滾操作本質(zhì)上也是
對(duì)數(shù)據(jù)進(jìn)行修改,因此回滾時(shí)對(duì)數(shù)據(jù)的操作也會(huì)記錄到 Redo Log 中。
一個(gè)回滾了的事務(wù)的 Redo Log,看起來(lái)是這樣的:
記錄 1: trx1, Undo log insert undo_insert …
記錄 2: trx1, insert A…
記錄 3: trx1, Undo log insert undo_update …
記錄 4: trx1, update B…
記錄 5: trx1, Undo log insert undo_delete …
記錄 6: trx1, delete C…
記錄 7: trx1, insert C
記錄 8: trx1, update B to old value
記錄 9: trx1, delete A
一個(gè)被回滾了的事務(wù)在恢復(fù)時(shí)的操作就是先 redo 再 undo,因此不會(huì)破壞數(shù)據(jù)的一致性.
– InnoDB 存儲(chǔ)引擎中相關(guān)的函數(shù)
Redo: recv_recovery_from_checkpoint_start()
Undo: recv_recovery_rollback_active()
Undo Log 的 Redo Log: trx_undof_page_add_undo_rec_log()
關(guān)于“mysql 中 undo log 及 redo log 是什么”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。