發現本身的知識點有點散,今天就把它們鏈接起來,好好總結一下。html
定義和做用 | 所在架構層級 | 日誌形式 | 所在文件和默認名稱,組織結構 | 是否緩存,如何緩存 | 寫文件方式 | |||
undo log | 回滾日誌,在事務執行的過程當中操做任何數據以前先將數據備份到undolog中。mysql 事務失敗時可根據undo log進行回滾。sql 用來保證事務的一致性。數據庫 還能夠用來實現多版本併發控制MVCC。緩存 |
InnoDB引擎層 | 邏輯日誌,以行的形式進行記錄。 | 共享表空間文件,ibdata0/ibdata1。架構 undo只是該文件的的一部分(rollback segment),文件由頁組成,每一頁又由一行行的數據組成,undo相對有本身的固定頁,會循環覆蓋。併發 Rollback segment,一共有128個,分別從resg slot0 - resg slot127,每個resg slot,也就是每個回滾段,內部由1024個undo segment組成。分佈式 |
是,innodb_buffer_pool緩衝池中有undo頁 | 儘可能順序寫。 post 回滾,實際作的是與以前相反的工做,好比INSERT須要的是DELETE,而DELETE須要的是INSERT。url 執行相反的UPDATE,將修改前的行放回去。 回滾操做寫入磁盤時爲隨機寫。 |
||
redo log | 重作日誌,在事務執行的過程當中不斷記錄事務操做的變化。 恢復提交後的物理數據頁(恢復數據頁,且只能恢復到最後一次提交的位置)。 用來保證事務的原子性和持久性。 |
InnoDB引擎層 | 物理日誌,記錄的是數據頁的物理修改。 | 重作日誌文件,ib_logfile0/ib_logfile1。 有本身的頁結構,會循環覆蓋。 |
是,專門的獨立的redo緩衝區 | 儘可能順序寫。 先寫入日誌緩衝中,而後按照必定的條件順序寫入redo日誌文件。 恢復操做寫入磁盤時爲隨機寫。
|
||
binlog | 二進制日誌,在事務提交後進行記錄。 用來備份, 經過主從複製來實現數據同步和讀寫分離。 |
MySQL數據庫(上)層 | 邏輯日誌,記錄數據庫全部增刪改操做(sql語句)。 | 二進制日誌文件,localhost-bin.000001~localhost-bin.00000n。 有本身的文件格式和文件結構,不會循環覆蓋,追加寫,文件寫滿再新建。 |
是,每一個會話有一個默認32K的緩衝。 | 順序寫。 |
Undo 記錄某數據被修改前的值,能夠用來在事務失敗時進行rollback;重要的是,undo log會產生redo log,也就是undo log的產生也會伴隨redo log的產生,這是由於undo log也須要持久性的保護。即undo也是數據頁的一部分。
Redo 記錄某數據塊被修改後的值,能夠用來恢復未寫入data file 的已成功事務更新的數據。即redo log是對數據頁修改後刷髒的一個有力補充。即WAL技術,Write-Ahead Logging,先寫日誌文件,再寫到數據庫頁緩存,最後刷到磁盤的數據庫中。
例如某一事務的事務序號爲T1,其對數據X進行修改,設X的原值是5,修改後的值爲15,那麼Undo日誌爲<T1, X, 5>,Redo日誌爲<T1, X, 15>。
redo log是在事務進行中不斷被寫入,因此每一個事務對應多個日誌條目。
binlog 是在事務提交完成後,進行一次寫入。因此對於每一個事務僅僅對應一個日誌記錄。
redo log日誌刷盤機制和參數innodb_flush_log_at_trx_commit有關。
binlog 何時刷新到磁盤跟參數sync_binlog
有關。
innodb_flush_log_at_trx_commit
0: 每隔1s,由系統後臺線程刷log buffer,也就是把redo日誌刷盤,這裏會調用fsync,因此可能丟失最後1s的事務。
1: 每次commit時,刷redo日誌,肯定fsync刷盤。爲默認值。
2: 每次提交時,刷redo日誌到文件系統,不調用fsync刷盤,5.6.6以前是每隔1s刷盤,以後的版本是經過參數innodb_flush_log_at_timeout設置,默認也是1s。因此也可能丟最後一秒的事務。若是有掉電保護組件的話,能夠開啓。
sync_binlog
表示每多少個sync事件觸發一次真正的binlog fsync刷盤,默認是1,表示每次commit時binlog都會fsync。
建議這兩個參數都設置成1.
InnoDB存儲引擎提供了對XA事務的支持,並經過XA事務來支持分佈式事務的實現。
分佈式事務(Distributed Transactions)指的是容許多個獨立的事務資源(transactional resources)參與到一個全局的事務中。全局事務也必須遵循ACID原則。
XA事務容許不一樣數據庫之間的分佈式事務,例如一臺MySQL數據,一臺Oracle數據庫,只要全局事務中的每一個節點都支持XA事務便可。此時,InnoDB的隔離級別必須是SERIALIZABLE。
分佈式事務採用兩階段提交(two-phase commit)的方式。
在第一階段,全部參與全局事務的節點開始準備(PREPARE),告訴事務管理器它們準備好提交了。
在第二階段,事務管理器告訴資源管理器執行ROLLBACK仍是COMMIT。若是任何一個節點顯示不能提交,則全部節點被告知須要回滾。
因此,與本地事務對比,分佈式事務多了一次PREPARE操做,待收到全部節點的贊成信息後,再進行提交或者回滾操做。
以上討論的是外部事務,即資源管理器是MySQL數據庫自己。而在MySQL數據庫內部也能夠存在這樣相似的分佈式事務。
資源管理器能夠是存儲引擎或插件,因此能夠是存儲引擎和插件之間,或者存儲引擎與存儲引擎之間,這種被稱爲內部XA事務。
最爲常見的內部XA事務存在於binlog與InnoDB存儲引擎之間。
既然是XA事務,必然涉及到兩階段提交,對於內部XA而言,一樣存在着提交的兩個階段。
這個兩階段提交是在開啓binlog以後,redo與binlog的兩階段提交。
在更新一條數據時,會先執行,而後寫入redo log中,redo log進入prepare狀態,執行器執行完成。
而後執行器生成這個操做的binlog,並寫入磁盤。
而後提交commit,更新完成。
假設在任何狀況下(機器掉電)mysqld crash或者os crash,MySQL仍然能保證數據庫的一致性。數據的一致性是如何作到的哪?正是二階段提交。
咱們結合幾種場景來分析下二階段提交是如何作到的:
1.prepare階段,redo log落盤前,mysqld crash
2.prepare階段,redo log落盤後,binlog落盤前,mysqld crash
3.commit階段,binlog落盤後,mysqld crash
對於第一種狀況,因爲redo沒有落盤,毫無疑問,事務的更新確定沒有寫入磁盤,數據庫的一致性不受影響;
對於第二種狀況,這時候redo log寫入完成,但binlog還未寫入,是提交仍是回滾呢?
對於第三種狀況,此時,redo log和binlog都已經落盤,只是undo狀態沒有更新,雖然redo log和binlog已經一致了,事務是否應該提交?
對於第三種狀況,咱們能夠蒐集到未提交事務的binlog event,因此須要提交;
對於第二種狀況,因爲binlog未寫入,須要經過執行回滾操做來保證數據庫的一致性。
簡而言之,對於異常的XA事務,若binlog已落盤,則事務應該提交;binlog未落盤,則事務就應該回滾。
注:以上XA事務的2PC流程主要參考第二篇,和書上稍微有些差異,書上寫的是先提交binlog,我以爲可能更合理。可是不影響對事務2PC的總體理解。
參考資料:
《MySQL技術內幕InnoDB存儲引擎》