標籤:

關於Innodb undo log的刷新時機?

在看《資料庫系統實現》的時候發現關於undo log 的描述,修改前寫入undo log, redo log有緩存,那麼undo記錄呢,它的磁碟寫入時機是什麼,是直接同步寫入么。undo數據的持久化和數據頁的持久化關係又是什麼。

Undo + Redo事務的簡化過程

假設有A、B兩個數據,值分別為1,2,開始一個事務,事務的操作內容為:把1修改為3,2修改為4,那麼實際的記錄如下(簡化):

A.事務開始.

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.事務提交

不太理解上述過程undo log的持久化時機。


修改前寫入undo的原因是直接修改了數據,在上述書上提供的方案里(page方式),page的刷出是不做控制的,也就意味著修改數據的時候page雖然fix在buffer裡面,但是有可能在redo log落盤之前被刷出到磁碟,所以如果undo log沒有先落盤會導致無法回滾。順序是先寫undo log,修改數據,再寫redo log。回放的時候先回放redo log,再把沒提交的事務undo掉。

Innodb這種事實上是undo 通過undo段生成undo page,undo page跟數據一起被當做修改寫redo log, redo log通過多個mtr落盤。重啟時先回放redo,從redo構造undo page再undo掉回滾的事務。mvcc可以通過undo page實現。

其他一些wal方式各有不同。

只用redo的,要求redo落盤前page不能刷出,否則臟頁一旦落盤不能回滾,所以長事務下,內存佔用比較高。回放的時候只回放redo,沒有提交的事務本身在內存中回滾了。另外page在buffer中也需要維護多版本,或者記錄undo page但是不寫undo log,總之要保證能在內存中回滾。多版本通過日誌之外的方式實現。常見的是基於LSM的實現。

只用undo的,事務提交的時候臟頁要刷出,否則可能丟失更新,所以時延比較大。沒怎麼見過。主要還是書上說的吧。重啟也沒什麼要回放的了。undo用來支持多版本。

基於LSM的可以考慮只記redolog,因為沒有直接修改數據,而是生成了新的版本,而且不需要把page fix,內存開銷比較小。

上述假定都是基於redo log寫一條的前提,事實上這種方式不能做長事務,現實情況可以參考innodb的mtr


毫無疑問,一個事務的完成最重要的一個標誌就是日誌必須落盤(持久化)一條日誌記錄包括redo記錄和undo記錄,我們通常把redo記錄稱為redo log,把undo記錄稱為undo log,一個事務可能有多次的寫操作,所以如果每寫一條記錄,就寫一次盤,性能接受不了,所以在一個事務未提交之前,日誌會寫進log buffer中,在事務提交的時候或者buffer被寫滿的時候,將log刷到磁碟上,log成功落盤後事務才能應答成功,所以如果沒有事務並發提交,一個事務完成,至少有一次的落盤操作

為了進一步優化落盤性能,減少落盤次數,如果是有並發的事務提交,還可能會把並發提交的事務日誌做一個合併,一次性寫入到磁碟中


推薦閱讀:

mysql 如何演示不可重複讀
MySQl中JOIN後面的子查詢語句得到的結果叫做「視圖」嗎?
MySQL主資料庫負責增刪改,從資料庫負責增改怎麼配置?
如何MySQL鏈接Excel,實現一個簡易的自動更新報表?
使用ECharts如何從mysql資料庫取數據顯示在頁面?

TAG:MySQL | InnoDB |