MySQL日誌—Undo | Redo

00 – Undo Loghtml

Undo Log 是爲了實現事務的原子性,在MySQL數據庫InnoDB存儲引擎中,還用Undo Log來實現多版本併發控制(簡稱:MVCC)。mysql

- 事務的原子性(Atomicity)sql

  事務中的全部操做,要麼所有完成,要麼不作任何操做,不能只作部分操做。若是在執行的過程當中發生數據庫

  了錯誤,要回滾(Rollback)到事務開始前的狀態,就像這個事務歷來沒有執行過。緩存

- 原理併發

  Undo Log的原理很簡單,爲了知足事務的原子性,在操做任何數據以前,首先將數據備份到一個地方函數

  (這個存儲數據備份的地方稱爲Undo Log)。而後進行數據的修改。若是出現了錯誤或者用戶執行了性能

  ROLLBACK語句,系統能夠利用Undo Log中的備份將數據恢復到事務開始以前的狀態。設計

除了能夠保證事務的原子性,Undo Log也能夠用來輔助完成事務的持久化。日誌

- 事務的持久性(Durability)

  事務一旦完成,該事務對數據庫所作的全部修改都會持久的保存到數據庫中。爲了保證持久性,數據庫

  系統會將修改後的數據徹底的記錄到持久的存儲上。

- 用Undo Log實現原子性和持久化的事務的簡化過程

  假設有A、B兩個數據,值分別爲1,2。

  A.事務開始.

  B.記錄A=1到undo log.

  C.修改A=3.

  D.記錄B=2到undo log.

  E.修改B=4.

  F.將undo log寫到磁盤。

  G.將數據寫到磁盤。

  H.事務提交

  這裏有一個隱含的前提條件:‘數據都是先讀到內存中,而後修改內存中的數據,最後將數據寫回磁盤’。

  之因此能同時保證原子性和持久化,是由於如下特色:

  A. 更新數據前記錄Undo log。

  B. 爲了保證持久性,必須將數據在事務提交前寫到磁盤。只要事務成功提交,數據必然已經持久化。

  C. Undo log必須先於數據持久化到磁盤。若是在G,H之間系統崩潰,undo log是完整的,

     能夠用來回滾事務。

  D. 若是在A-F之間系統崩潰,由於數據沒有持久化到磁盤。因此磁盤上的數據仍是保持在事務開始前的狀態。

缺陷:每一個事務提交前將數據和Undo Log寫入磁盤,這樣會致使大量的磁盤IO,所以性能很低。

若是可以將數據緩存一段時間,就能減小IO提升性能。可是這樣就會喪失事務的持久性。所以引入了另一

種機制來實現持久化,即Redo Log.

01 – Redo Log

- 原理

  和Undo Log相反,Redo Log記錄的是新數據的備份。在事務提交前,只要將Redo Log持久化便可,

  不須要將數據持久化。當系統崩潰時,雖然數據沒有持久化,可是Redo Log已經持久化。系統能夠根據

  Redo Log的內容,將全部數據恢復到最新的狀態。

- Undo + Redo事務的簡化過程

  假設有A、B兩個數據,值分別爲1,2.

  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 + Redo事務的特色

  A. 爲了保證持久性,必須在事務提交前將Redo Log持久化。

  B. 數據不須要在事務提交前寫入磁盤,而是緩存在內存中。

  C. Redo Log 保證事務的持久性。

  D. Undo Log 保證事務的原子性。

  E. 有一個隱含的特色,數據必需要晚於redo log寫入持久存儲。

- IO性能

  Undo + Redo的設計主要考慮的是提高IO性能。雖然說經過緩存數據,減小了寫數據的IO.

  可是卻引入了新的IO,即寫Redo Log的IO。若是Redo Log的IO性能很差,就不能起到提升性能的目的。

  爲了保證Redo Log可以有比較好的IO性能,InnoDB 的 Redo Log的設計有如下幾個特色:

  A. 儘可能保持Redo Log存儲在一段連續的空間上。所以在系統第一次啓動時就會將日誌文件的空間徹底分配。

     以順序追加的方式記錄Redo Log,經過順序IO來改善性能。

  B. 批量寫入日誌。日誌並非直接寫入文件,而是先寫入redo log buffer.當須要將日誌刷新到磁盤時

     (如事務提交),將許多日誌一塊兒寫入磁盤.

  C. 併發的事務共享Redo Log的存儲空間,它們的Redo Log按語句的執行順序,依次交替的記錄在一塊兒,

     以減小日誌佔用的空間。例如,Redo Log中的記錄內容多是這樣的:

     記錄1: <trx1, insert …>

     記錄2: <trx2, update …>

     記錄3: <trx1, delete …>

     記錄4: <trx3, update …>

     記錄5: <trx2, insert …>

  D. 由於C的緣由,當一個事務將Redo Log寫入磁盤時,也會將其餘未提交的事務的日誌寫入磁盤。

  E. Redo Log上只進行順序追加的操做,當一個事務須要回滾時,它的Redo Log記錄也不會從

     Redo Log中刪除掉。

02 – 恢復(Recovery)

- 恢復策略

  前面說到未提交的事務和回滾了的事務也會記錄Redo Log,所以在進行恢復時,這些事務要進行特殊的

  的處理.有2中不一樣的恢復策略:

  A. 進行恢復時,只重作已經提交了的事務。

  B. 進行恢復時,重作全部事務包括未提交的事務和回滾了的事務。而後經過Undo Log回滾那些

     未提交的事務。

- InnoDB存儲引擎的恢復機制

  MySQL數據庫InnoDB存儲引擎使用了B策略, InnoDB存儲引擎中的恢復機制有幾個特色:

  A. 在重作Redo Log時,並不關心事務性。 恢復時,沒有BEGIN,也沒有COMMIT,ROLLBACK的行爲。

     也不關心每一個日誌是哪一個事務的。儘管事務ID等事務相關的內容會記入Redo Log,這些內容只是被看成

     要操做的數據的一部分。

  B. 使用B策略就必需要將Undo Log持久化,並且必需要在寫Redo Log以前將對應的Undo Log寫入磁盤。

     Undo和Redo Log的這種關聯,使得持久化變得複雜起來。爲了下降複雜度,InnoDB將Undo Log看做

     數據,所以記錄Undo Log的操做也會記錄到redo log中。這樣undo log就能夠象數據同樣緩存起來,

     而不用在redo log以前寫入磁盤了。

     包含Undo Log操做的Redo Log,看起來是這樣的:

     記錄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. 到這裏,還有一個問題沒有弄清楚。既然Redo沒有事務性,那豈不是會從新執行被回滾了的事務?

     確實是這樣。同時Innodb也會將事務回滾時的操做也記錄到redo log中。回滾操做本質上也是

     對數據進行修改,所以回滾時對數據的操做也會記錄到Redo Log中。

     一個回滾了的事務的Redo Log,看起來是這樣的:

     記錄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>

     一個被回滾了的事務在恢復時的操做就是先redo再undo,所以不會破壞數據的一致性.

- InnoDB存儲引擎中相關的函數

  Redo: recv_recovery_from_checkpoint_start()

  Undo: recv_recovery_rollback_active()

  Undo Log的Redo Log: trx_undof_page_add_undo_rec_log()

轉載至:http://www.mysqlops.com/2012/04/06/innodb-log1.html

相關文章
相關標籤/搜索