1. 程式人生 > >MySQL二階段提交以及xtrabackup如何保證備份不丟失資料

MySQL二階段提交以及xtrabackup如何保證備份不丟失資料

MySQL二階段提交與xtrabackup如何保證備份不丟失資料
MySQL二階段提交與crash recovery
1. MySQL二階段提交
2. crash recovery的實現
xtrabackup如何實現資料不丟失
1. general log中xtrabackup的備份記錄

MySQL二階段提交與xtrabackup如何保證備份不丟失資料

  • 前提:設定了雙1

MySQL二階段提交與crash recovery

1. MySQL二階段提交


  • 如圖,當用戶提交事務的時候,當設定了雙1,會進行redo日誌的實時重新整理。實際上,即使一個事務還沒有commit,只是執行到了insert,此時redo就已經實時開始記錄資料頁的變化了(undo記錄修改前的資料);當事務commit之後,首先會打上prepare的標記,也就是二階段提交的redo prepare階段,此時redo日誌已經開始了fsync刷盤動作。
  • 當redo prepare完成後,返回ok;然後開始寫binlog buffer,並且開始fsync刷盤到binlog。此時為二階段提交的binlog fsync階段。

    redo log具體的實現方式與設計特點: 
    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中刪除掉。 
    來源: 

    http://www.cnblogs.com/Bozh/archive/2013/03/18/2966494.html 
    PS: undo的變化也會記錄在redo中。InnoDB將Undo Log看作資料,因此記錄Undo Log的操作也會記錄到redo log中。這樣undo log就可以象資料一樣快取起來,而不用在redo log之前寫入磁碟了。在redo持久化的同時,就能將undo也順帶持久化了。

  • 當binlog刷盤完成後,然後會將redo中對應事務的prepare標記修改為commit,表明經過上述過程,事務已經在日誌(binlog以及redo)裡面完成了commit,對應的是二階段提交的redo commit階段。redo commit標記這個事務已經在innodb層redo日誌中被提交,後續做crash recovery的時候需要前滾(如果資料還未落盤)。

2. crash recovery的實現

MySQL在做crash recovery的時候,會去比對redo中記錄的LSN與資料頁中的LSN。

  • 如果redo中的LSN號小,則不需要對該頁恢復資料。
  • 如果redo中的LSN號大(資料還未刷到磁碟),
    • 並且事務已經有了commit標記,則前滾;
    • 如果事務帶有的是prepare標記,這個時候就需要結合binlog來判斷這條事務是需要前滾還是回滾: 
      - 如果這條事務在binlog中沒有,則回滾; 
      - 如果這條事務已經刷到了binlog日誌檔案中,則這個事務會被重新提交併在redo log中打上commit標記。(這樣的話 也可以保證主從資料的一致)
    • 如果事務既不帶prepare標記,也不帶commit標記,則回滾。
  • 由此我們可以看到,MySQL在做恢復的時候,並不是單純的依靠redo、undo來做資料正常恢復,還需要結合binlog中的事務資訊,與redo中的進行比對,再決定某些事務是否需要前滾。 
    那麼,xtrabackup備份過程是不備份binlog的,它又是如何實現資料的一致性?

xtrabackup如何實現資料不丟失

1. general log中xtrabackup的備份記錄


 
  1. 13 Connect [email protected] on
  2. 13 Query SET SESSION wait_timeout=2147483
  3. 13 Query SHOW VARIABLES
  4. 13 Query SHOW ENGINE INNODB STATUS
  5. 170507 22:12:29 13 Query SET SESSION lock_wait_timeout=31536000
  6. 13 Query FLUSH NO_WRITE_TO_BINLOG TABLES
  7. 13 Query FLUSH TABLES WITH READ LOCK
  8. 170507 22:12:39 13 Query SHOW MASTER STATUS
  9. 13 Query SHOW VARIABLES
  10. 13 Query FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS
  11. 13 Query UNLOCK TABLES
  12. 13 Query SELECT UUID()
  13. 13 Query SELECT VERSION()
  14. 13 Quit
  • FLUSH TABLES會關閉所有開啟的表,等待所有事物結束並關閉開啟的表。
  • FLUSH TABLES WITH READ LOCK會加一把全域性讀鎖,阻止新的修改資料的操作。
  • SHOW MASTER STATUS獲取一致性位點。在加全域性讀鎖的情況下,資料不會有更新,所以這個時候資料庫狀態是一致的。
  • FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS 這個操作會將Innodb層的redo日誌進行持久化刷到磁碟,然後再拷貝redo日誌,保證了redo日誌是最新,保證資料一致性。那如何與binlog做協調?怎麼保證redo記錄的資料與binlog資料是一致的?這個應該就是結合SHOW MASTER STATUS來確定拷貝所獲取到的binlog file以及binlog pos對應的redo點為止,也就是一致性位點。而FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS確保了還在重做日誌緩衝中的commit標記,持久化重新整理到redo日誌中並落盤;確保不丟掉這個事務。