數據庫日志redo和undo


數據庫的ACID屬性

Atomicity:原子性,以事物transact為最小單位,事物中的所有操作,要么都執行完,要么都不執行,不存在一部分操作執行,另一部分操作不執行的情況。

Consistency:一致性,在事物開始和事物完成后,數據庫的完整性限制不會改變。

Isolation:隔離性,同一個數據庫中同時並發執行多個事務,事物之間的操作不會相互影響。

Durability:持久性,事物完成之后,事物所作的操作會持久存在於數據庫中。

 

Redo log 和undo log

Redo log:由DML(insert delete update)操作,引起的頁面變化,都需要記錄到redo log中,大部分為物理日志

在頁面修改完成之后,在臟數據由cache寫入到磁盤之前,會寫入redo日志中。

日志先行,日志會先寫入到磁盤中,數據后寫入

聚簇索引/二級索引/undo頁面的修改,均需要記錄在redo日志中

 

Redo log是啥?官方文檔解釋如下:

Redo log是一個基於磁盤的數據格式,在數據庫災難恢復過程中,用於恢復未完成的事物,修復數據的。在正常的操作過程中,redo log將來自於SQL 語句或者其他API調用的請求,轉化為數據表中的變化,當對數據的改變操作還未完成之前,遭遇了意外的停機,那這些變化會在數據庫啟動初始化的過程中進行replay重演,這個重演的過程,是在接受client請求之前,就會完成。

默認情況下,redo log在磁盤上的體現,一般是ib_logfile0和ib_logfile1兩個文件,mysql以循環的方式,寫這兩個文件,在redo log中的數據,是以記錄變化為編碼,這些日志數據,也就體現了數據的變化,在log中的一段內容,就體現了一個已經增加的LSN增量。

在mysql的配置文件中,innodb_log_file_size設置了redo log文件的大小,innodb_log_file_in_group設置了日志文件的個數,這些設置必須重啟才能生效,當innodb檢測到設置的大小和當前的文件大小不一致時,會設置一個檢查點,然后關閉該日志文件,刪除舊文件,創建一個設置大小的日志文件,開始寫入日志。

Redo log刷盤的組提交

和其他所有兼容ACID模型的數據庫引擎一樣,innodb數據引擎也是會在事物提交之前,先將redo log文件刷盤,而且innodb還使用了一種組提交機制,同時將多個事務的redo log刷到磁盤中,避免一個事物一個提交,通過該組提交機制,一次日志刷盤操作,會將同時進行的多個事務的redo log提交,提高了中斷效率。

 

 

Undo log:由DML    操作導致的數據記錄變化,均需要將變化前的鏡像,寫入到undo log中,是一種邏輯日志。

undo log是啥?官方文檔解釋如下:

undo log是一組undo log記錄的集合,這些undo log記錄是關於某個事物的,一個undo log記錄中包含了描述如何將最后的更新回退到集群索引記錄的信息,如果有某一個事物需要去使用原始數據(比如在一個一致性的讀事物中),這些原始沒有被修改的數據,就會通過undo log記錄進行恢復。Undo log存在於undo log段中,undo log段中包含了回滾段,而回滾段存在於系統表空間、臨時表空間和回滾表空間中。

Innodb支持128個回滾段,其中有32個是為臨時表的事物操作預留的,每一個更新臨時表的事物(不包含只讀事物)會被分配2個回滾段,一個是啟用了redo的回滾段,另一個是沒有啟用redo的回滾段。只讀事物只會分配一個沒有啟用redo的回滾段,因為只讀事物是只允許修改臨時表的。

剩下的96個回滾段,每一個都支持1023個一致性數據修改事物,所以能夠支持近似於96K的一致性數據修改事物,96K的限制是假設事物不會去修改臨時表,如果所有的數據修改事物都修改了臨時表,這個大小大約是32K。

 

既然DML操作,會引起redo log和undo log的變化,具體進行分析一下。

Insert 插入操作:

Insert插入操作,不會對原有數據產生影響,只是新產生一條記錄和對應的索引,以前的記錄和索引不會被修改,所以對undo log的要求不高,但是對redo log的要求就比較高了,用於replay,就需要整條插入的所有信息。

Undo log:記錄insert插入記錄的主鍵值

Redo log:記錄日志操作頁面(space_id,page_no)、完整的插入記錄、系統列等

 

Delete刪除操作

Delete刪除操作是要從當前的庫或者表中刪除一部分已經存在的記錄,如果在刪除過程中出現了數據庫的crash,在recovery過程中需要再次進行刪除操作,而recovery中的replay利用的就是redo log,所以redo log中需要記錄刪除的具體信息,比如主鍵等關鍵信息;而在undo log中需要記錄的信息就會更多了,因為有可能在執行刪除事物之前,存在一個一致性的讀事物,需要讀取當前被刪除的這些記錄,所以這些刪除的記錄的原始數據,是要存放在undo log中的;另外,由於讀查詢是會使用到索引等信息,所以這些索引信息,也是要存放在undo log中的。所以綜上:

Redo log:記錄日志操作頁面、刪除記錄的系統列,記錄在頁面中的位置,同時記錄undo page的修改

Undo log:

  1. Delete操作在innodb中為delete mark操作,並不是真的刪除數據,只是將記錄標記為delete
  2. 記錄當前刪除記錄的系統列
  3. 記錄當前刪除記錄的主鍵
  4. 記錄當前刪除記錄的所有索引

 

Update操作

Update的操作分為三種情況,對於不同的操作情況,redo log和undo log中記錄的信息也是不一樣的。

Section 1:未修改索引,修改的屬性列長度不變

在這種update場景中,只是對非索引列的值進行了修改,並未修改該列的長度,所以在redo log中,會進行定點的update,會記錄的是update log;而在undo log中,需要記錄的是update操作的系統列、操作記錄的主鍵、操作記錄該列的原值,如果該update列中包含二級索引,二級索引的原值,也需要記錄到undo log中。綜上:

Redo log:記錄update redo log,如果更新列中包含二級索引,則需要對二級索引進行delete mark操作,然后重新insert一條新的二級索引;同時對undo 頁面的修改,同步也要寫入到redo log中。

Undo log:記錄update的系統列、操作記錄的主鍵、操作記錄該列的原值。如果該update列中包含二級索引,二級索引的原值,也需要記錄到undo log中

Section 2:未修改索引,修改了屬性列長度

這種update場景和section 1中的場景類似,唯一的區別是屬性列長度發生了變化,這中變化,在undo log中記錄的信息,和section 1中的信息形同,而redo log中記錄的信息會發生變化,這個時候記錄的不再是定點的update,應該是先delete原始的信息,然后insert一條信息。

undo log:記錄信息和section 1中的undo log信息相同

redo log:不能定點的update了,會記錄delete+insert redo log

section 3:修改索引列值

在數據庫中,修改某條記錄的索引列值,實際上的操作是將該記錄delete,然后重新插入一條新的記錄,然后生成索引,更新索引表。在這一連串的操作過程中,redo log實際上是要記錄一個delete和一個insert的redo log,而undo log上是要記錄原始的記錄(delete操作)和insert的操作記錄。

 

 

LSN:log sequence number

日志序列號,遞增產生,一個LSN可以唯一標識一個redo log,其中有一個叫checkpoint LSN,用來標識數據庫crash的redo 起始點,LSN和日志文件位置意義對應。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM