MySQL中的redo及undo簡(jiǎn)單分析-創(chuàng)新互聯(lián)

本文主要給大家介紹MySQL中的redo及undo簡(jiǎn)單分析,希望可以給大家補(bǔ)充和更新些知識(shí),如有其它問(wèn)題需要了解的可以持續(xù)在創(chuàng)新互聯(lián)建站行業(yè)資訊里面關(guān)注我的更新文章的。                                                 

成都創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括浪卡子網(wǎng)站建設(shè)、浪卡子網(wǎng)站制作、浪卡子網(wǎng)頁(yè)制作以及浪卡子網(wǎng)絡(luò)營(yíng)銷策劃等。多年來(lái),我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,浪卡子網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到浪卡子省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

我們都知道事務(wù)有4種特性:原子性、一致性、隔離性和持久性,在事務(wù)中的操作,要么全部執(zhí)行,要么全部不做,這就是事務(wù)的目的。事務(wù)的隔離性由鎖機(jī)制實(shí)現(xiàn),原子性、一致性和持久性由事務(wù)的redo 日志和undo 日志來(lái)保證。所以本篇文章將討論關(guān)于事務(wù)中的redo和undo的幾個(gè)問(wèn)題:

  • redo 日志與undo日志分別是什么?

  • redo 如何保證事務(wù)的持久性?

  • undo log 是否是redo log的逆過(guò)程?

  • Redo 的類型

重做日志(redo log)用來(lái)保證事務(wù)的持久性,即事務(wù)ACID中的D。實(shí)際上它可以分為以下兩種類型:

  • 物理Redo日志

  • 邏輯Redo日志

在InnoDB存儲(chǔ)引擎中,大部分情況下 Redo是物理日志,記錄的是數(shù)據(jù)頁(yè)的物理變化。而邏輯Redo日志,不是記錄頁(yè)面的實(shí)際修改,而是記錄修改頁(yè)面的一類操作,比如新建數(shù)據(jù)頁(yè)時(shí),需要記錄邏輯日志。關(guān)于邏輯Redo日志涉及更加底層的內(nèi)容,這里我們只需要記住絕大數(shù)情況下,Redo是物理日志即可,DML對(duì)頁(yè)的修改操作,均需要記錄Redo.

Redo 的作用

Redo log的主要作用是用于數(shù)據(jù)庫(kù)的崩潰恢復(fù)

Redo 的組成

Redo log可以簡(jiǎn)單分為以下兩個(gè)部分:

  • 一是內(nèi)存中重做日志緩沖 (redo log buffer),是易失的,在內(nèi)存中

  • 二是重做日志文件 (redo log file),是持久的,保存在磁盤中

什么時(shí)候?qū)慠edo?

上面那張圖簡(jiǎn)單地體現(xiàn)了Redo的寫入流程,這里再細(xì)說(shuō)下寫入Redo的時(shí)機(jī):

  • 在數(shù)據(jù)頁(yè)修改完成之后,在臟頁(yè)刷出磁盤之前,寫入redo日志。注意的是先修改數(shù)據(jù),后寫日志

  • redo日志比數(shù)據(jù)頁(yè)先寫回磁盤

  • 聚集索引、二級(jí)索引、undo頁(yè)面的修改,均需要記錄Redo日志。

Redo的整體流程

下面以一個(gè)更新事務(wù)為例,宏觀上把握redo log 流轉(zhuǎn)過(guò)程,如下圖所示:

MySQL中的redo及undo簡(jiǎn)單分析

  • 第一步:先將原始數(shù)據(jù)從磁盤中讀入內(nèi)存中來(lái),修改數(shù)據(jù)的內(nèi)存拷貝

  • 第二步:生成一條重做日志并寫入redo log buffer,記錄的是數(shù)據(jù)被修改后的值

  • 第三步:當(dāng)事務(wù)commit時(shí),將redo log buffer中的內(nèi)容刷新到 redo log file,對(duì) redo log file采用追加寫的方式

  • 第四步:定期將內(nèi)存中修改的數(shù)據(jù)刷新到磁盤中

redo如何保證 事務(wù)的持久性?

InnoDB是事務(wù)的存儲(chǔ)引擎,其通過(guò)Force Log at Commit 機(jī)制實(shí)現(xiàn)事務(wù)的持久性,即當(dāng)事務(wù)提交時(shí),先將 redo log buffer 寫入到 redo log file 進(jìn)行持久化,待事務(wù)的commit操作完成時(shí)才算完成。這種做法也被稱為Write-Ahead Log(預(yù)先日志持久化),在持久化一個(gè)數(shù)據(jù)頁(yè)之前,先將內(nèi)存中相應(yīng)的日志頁(yè)持久化。

為了保證每次日志都寫入redo log file,在每次將redo buffer寫入redo log file之后,默認(rèn)情況下,InnoDB存儲(chǔ)引擎都需要調(diào)用一次fsync操作,因?yàn)橹刈鋈罩敬蜷_(kāi)并沒(méi)有 O_DIRECT選項(xiàng),所以重做日志先寫入到文件系統(tǒng)緩存。為了確保重做日志寫入到磁盤,必須進(jìn)行一次 fsync操作。fsync是一種系統(tǒng)調(diào)用操作,其fsync的效率取決于磁盤的性能,因此磁盤的性能也影響了事務(wù)提交的性能,也就是數(shù)據(jù)庫(kù)的性能。
(O_DIRECT選項(xiàng)是在Linux系統(tǒng)中的選項(xiàng),使用該選項(xiàng)后,對(duì)文件進(jìn)行直接IO操作,不經(jīng)過(guò)文件系統(tǒng)緩存,直接寫入磁盤)

上面提到的Force Log at Commit機(jī)制就是靠InnoDB存儲(chǔ)引擎提供的參數(shù)innodb_flush_log_at_trx_commit來(lái)控制的,該參數(shù)可以控制 redo log刷新到磁盤的策略,設(shè)置該參數(shù)值也可以允許用戶設(shè)置非持久性的情況發(fā)生,具體如下:

  • 當(dāng)設(shè)置參數(shù)為1時(shí),(默認(rèn)為1),表示事務(wù)提交時(shí)必須調(diào)用一次fsync操作,最安全的配置,保障持久性

  • 當(dāng)設(shè)置參數(shù)為2時(shí),則在事務(wù)提交時(shí)只做write操作,只保證將redo log buffer寫到系統(tǒng)的頁(yè)面緩存中,不進(jìn)行fsync操作,因此如果MySQL數(shù)據(jù)庫(kù)宕機(jī)時(shí) 不會(huì)丟失事務(wù),但操作系統(tǒng)宕機(jī)則可能丟失事務(wù)

  • 當(dāng)設(shè)置參數(shù)為0時(shí),表示事務(wù)提交時(shí)不進(jìn)行寫入redo log操作,這個(gè)操作僅在master thread 中完成,而在master thread中每1秒進(jìn)行一次重做日志的fsync操作,因此實(shí)例 crash 最多丟失1秒鐘內(nèi)的事務(wù)。(master thread是負(fù)責(zé)將緩沖池中的數(shù)據(jù)異步刷新到磁盤,保證數(shù)據(jù)的一致性)

fsyncwrite操作實(shí)際上是系統(tǒng)調(diào)用函數(shù),在很多持久化場(chǎng)景都有使用到,比如 Redis 的AOF持久化中也使用到兩個(gè)函數(shù)。fsync操作 將數(shù)據(jù)提交到硬盤中,強(qiáng)制硬盤同步,將一直阻塞到寫入硬盤完成后返回,大量進(jìn)行fsync操作就有性能瓶頸,而write操作將數(shù)據(jù)寫到系統(tǒng)的頁(yè)面緩存后立即返回,后面依靠系統(tǒng)的調(diào)度機(jī)制將緩存數(shù)據(jù)刷到磁盤中去,其順序是user buffer——> page cache——>disk。

MySQL中的redo及undo簡(jiǎn)單分析

除了上面談到的Force Log at Commit機(jī)制保證事務(wù)的持久性,實(shí)際上重做日志的實(shí)現(xiàn)還要依賴于mini-transaction。

Redo在InnoDB中是如何實(shí)現(xiàn)的?與mini-transaction的聯(lián)系?

Redo的實(shí)現(xiàn)實(shí)則跟mini-transaction緊密相關(guān),mini-transaction是一種InnoDB內(nèi)部使用的機(jī)制,通過(guò)mini-transaction來(lái)保證并發(fā)事務(wù)操作下以及數(shù)據(jù)庫(kù)異常時(shí)數(shù)據(jù)頁(yè)中數(shù)據(jù)的一致性,但它不屬于事務(wù)。

為了使得mini-transaction保證數(shù)據(jù)頁(yè)數(shù)據(jù)的一致性,mini-transaction必須遵循以下三種協(xié)議

  • The FIX Rules

  • Write-Ahead Log

  • Force-log-at-commit

The FIX Rules

修改一個(gè)數(shù)據(jù)頁(yè)時(shí)需要獲得該頁(yè)的x-latch(排他鎖),獲取一個(gè)數(shù)據(jù)頁(yè)時(shí)需要該頁(yè)的s-latch(讀鎖或者稱為共享鎖) 或者是 x-latch,持有該頁(yè)的鎖直到修改或訪問(wèn)該頁(yè)的操作完成。

Write-Ahead Log

在前面闡述中就提到了Write-Ahead Log(預(yù)先寫日志)。在持久化一個(gè)數(shù)據(jù)頁(yè)之前,必須先將內(nèi)存中相應(yīng)的日志頁(yè)持久化。每個(gè)頁(yè)都有一個(gè)LSN(log sequence number),代表日志序列號(hào),(LSN占用8字節(jié),單調(diào)遞增), 當(dāng)一個(gè)數(shù)據(jù)頁(yè)需要寫入到持久化設(shè)備之前,要求內(nèi)存中小于該頁(yè)LSN的日志先寫入持久化設(shè)備

那為什么必須要先寫日志呢?可不可以不寫日志,直接將數(shù)據(jù)寫入磁盤?原則上是可以的,只不過(guò)會(huì)產(chǎn)生一些問(wèn)題,數(shù)據(jù)修改會(huì)產(chǎn)生隨機(jī)IO,但日志是順序IO,append方式順序?qū)?,是一種串行的方式,這樣才能充分利用磁盤的性能。

Force-log-at-commit

這一點(diǎn)也就是前文提到的如何保證事務(wù)的持久性的內(nèi)容,這里再次總結(jié)一下,與上面的內(nèi)容相呼應(yīng)。在一個(gè)事務(wù)中可以修改多個(gè)頁(yè),Write-Ahead Log 可以保證單個(gè)數(shù)據(jù)頁(yè)的一致性,但是無(wú)法保證事務(wù)的持久性,F(xiàn)orce-log-at-commit 要求當(dāng)一個(gè)事務(wù)提交時(shí),其產(chǎn)生所有的mini-transaction 日志必須刷新到磁盤中,若日志刷新完成后,在緩沖池中的頁(yè)刷新到持久化存儲(chǔ)設(shè)備前數(shù)據(jù)庫(kù)發(fā)生了宕機(jī),那么數(shù)據(jù)庫(kù)重啟時(shí),可以通過(guò)日志來(lái)保證數(shù)據(jù)的完整性。

重做日志的寫入流程

MySQL中的redo及undo簡(jiǎn)單分析

上圖表示了重做日志的寫入流程,每個(gè)mini-transaction對(duì)應(yīng)每一條DML操作,比如一條update語(yǔ)句,其由一個(gè)mini-transaction來(lái)保證,對(duì)數(shù)據(jù)修改后,產(chǎn)生redo1,首先將其寫入mini-transaction私有的Buffer中,update語(yǔ)句結(jié)束后,將redo1從私有Buffer拷貝到公有的Log Buffer中。當(dāng)整個(gè)外部事務(wù)提交時(shí),將redo log buffer再刷入到redo log file中。

undo log

undo log的定義

undo log主要記錄的是數(shù)據(jù)的邏輯變化,為了在發(fā)生錯(cuò)誤時(shí)回滾之前的操作,需要將之前的操作都記錄下來(lái),然后在發(fā)生錯(cuò)誤時(shí)才可以回滾。

undo log的作用

undo是一種邏輯日志,有兩個(gè)作用:

  • 用于事務(wù)的回滾

  • MVCC

關(guān)于MVCC(多版本并發(fā)控制)的內(nèi)容這里就不多說(shuō)了,本文重點(diǎn)關(guān)注undo log用于事務(wù)的回滾。

undo日志,只將數(shù)據(jù)庫(kù)邏輯地恢復(fù)到原來(lái)的樣子,在回滾的時(shí)候,它實(shí)際上是做的相反的工作,比如一條INSERT ,對(duì)應(yīng)一條 DELETE,對(duì)于每個(gè)UPDATE,對(duì)應(yīng)一條相反的 UPDATE,將修改前的行放回去。undo日志用于事務(wù)的回滾操作進(jìn)而保障了事務(wù)的原子性。

undo log的寫入時(shí)機(jī)

  • DML操作修改聚簇索引前,記錄undo日志

  • 二級(jí)索引記錄的修改,不記錄undo日志

需要注意的是,undo頁(yè)面的修改,同樣需要記錄redo日志。

undo的存儲(chǔ)位置

在InnoDB存儲(chǔ)引擎中,undo存儲(chǔ)在回滾段(Rollback Segment)中,每個(gè)回滾段記錄了1024個(gè)undo log segment,而在每個(gè)undo log segment段中進(jìn)行undo 頁(yè)的申請(qǐng),在5.6以前,Rollback Segment是在共享表空間里的,5.6.3之后,可通過(guò) innodb_undo_tablespace設(shè)置undo存儲(chǔ)的位置。

undo的類型

在InnoDB存儲(chǔ)引擎中,undo log分為:

  • insert undo log

  • update undo log

insert undo log是指在insert 操作中產(chǎn)生的undo log,因?yàn)閕nsert操作的記錄,只對(duì)事務(wù)本身可見(jiàn),對(duì)其他事務(wù)不可見(jiàn)。故該undo log可以在事務(wù)提交后直接刪除,不需要進(jìn)行purge操作。

而update undo log記錄的是對(duì)delete 和update操作產(chǎn)生的undo log,該undo log可能需要提供MVCC機(jī)制,因此不能再事務(wù)提交時(shí)就進(jìn)行刪除。提交時(shí)放入undo log鏈表,等待purge線程進(jìn)行最后的刪除。

補(bǔ)充:purge線程兩個(gè)主要作用是:清理undo頁(yè)和清除page里面帶有Delete_Bit標(biāo)識(shí)的數(shù)據(jù)行。在InnoDB中,事務(wù)中的Delete操作實(shí)際上并不是真正的刪除掉數(shù)據(jù)行,而是一種Delete Mark操作,在記錄上標(biāo)識(shí)Delete_Bit,而不刪除記錄。是一種"假刪除",只是做了個(gè)標(biāo)記,真正的刪除工作需要后臺(tái)purge線程去完成。

undo log 是否是redo log的逆過(guò)程?

undo log 是否是redo log的逆過(guò)程?其實(shí)從前文就可以得出答案了,undo log是邏輯日志,對(duì)事務(wù)回滾時(shí),只是將數(shù)據(jù)庫(kù)邏輯地恢復(fù)到原來(lái)的樣子,而redo log是物理日志,記錄的是數(shù)據(jù)頁(yè)的物理變化,顯然undo log不是redo log的逆過(guò)程。

redo & undo總結(jié)

下面是redo log + undo log的簡(jiǎn)化過(guò)程,便于理解兩種日志的過(guò)程:

假設(shè)有A、B兩個(gè)數(shù)據(jù),值分別為1,2.
1. 事務(wù)開(kāi)始
2. 記錄A=1到undo log
3. 修改A=3
4. 記錄A=3到 redo log
5. 記錄B=2到 undo log
6. 修改B=4
7. 記錄B=4到redo log
8. 將redo log寫入磁盤
9. 事務(wù)提交

實(shí)際上,在insert/update/delete操作中,redo和undo分別記錄的內(nèi)容都不一樣,量也不一樣。在InnoDB內(nèi)存中,一般的順序如下:

  • 寫undo的redo

  • 寫undo

  • 修改數(shù)據(jù)頁(yè)

  • 寫Redo

小結(jié)

本文分析了事務(wù)中的redo和undo日志,參考了一些資料書籍整理得出,可能有些地方表述的不清楚。如有不對(duì)之處,歡迎指出。

以上就是MySQL事務(wù)中的redo與undo的分析(圖文)的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站制作公司其它相關(guān)文章!

本文名稱:MySQL中的redo及undo簡(jiǎn)單分析-創(chuàng)新互聯(lián)
本文路徑:http://muchs.cn/article0/cesoio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、品牌網(wǎng)站設(shè)計(jì)軟件開(kāi)發(fā)、網(wǎng)站策劃、做網(wǎng)站品牌網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司