MySQL Xtrabackup備份原理和實現細節
備份原理:
XtraBackup基于InnoDB的crash-recovery功能。它會復制innodb的data file,由于不鎖表,復制出來的數據是不一致的,在恢復的時候使用crash-recovery,使得數據恢復一致。
InnoDB維護了一個redo log,又稱為transaction log,事務日志,它包含了innodb數據的所有改動情況。當InnoDB啟動的時候,它會先去檢查data file和transaction log,并且會做二步操作:
XtraBackup在備份的時候, 一頁一頁地復制innodb的數據,而且不鎖定表,與此同時,XtraBackup還有另外一個線程監視著transactions log,一旦log發生變化,就把變化過的log pages復制走。
為什么要急著復制走呢? 因為transactions log文件大小有限,寫滿之后,就會從頭再開始寫,所以新數據可能會覆蓋到舊的數據。
在prepare過程中,XtraBackup使用復制到的transactions log對備份出來的innodb data file進行crash recovery。
官方原理:
在InnoDB內部會維護一個redo日志文件,我們也可以叫做事務日志文件。事務日志會存儲每一個InnoDB表數據的記錄修改。當InnoDB啟動時,InnoDB會檢查數據文件和事務日志,
并執行兩個步驟:它應用(前滾)已經提交的事務日志到數據文件,并將修改過但沒有提交的數據進行回滾操作。
xtrabackup在啟動時會記住log sequence number(LSN),并且復制所有的數據文件。復制過程需要一些時間,所以這期間如果數據文件有改動,那么將會使數據庫處于一個不同
的時間點。這時,xtrabackup會運行一個后臺進程,用于監視事務日志,并從事務日志復制最新的修改。
xtrabackup必須持續的做這個操作,是因為事務日志是會輪轉重復的寫入,并且事務日志可以被重用。所以xtrabackup自啟動開始,就不停的將事務日志中每個數據文件的修改都記錄下來。
上面就是xtrabackup的備份過程。接下來是準備(prepare)過程。在這個過程中,xtrabackup使用之前復制的事務日志,對各個數據文件執行災難恢復(就像
MySQL剛啟動時要做的一樣)。
當這個過程結束后,數據庫就可以做恢復還原了。
以上的過程在xtrabackup的編譯二進制程序中實現。程序innobackupex可以允許我們備份MyISAM表和frm文件從而增加了便捷和功能。Innobackupex會啟動xtrabackup,直到xtrabackup復制
數據文件后,然后執行FLUSH TABLES WITH READ LOCK來阻止新的寫入進來并把MyISAM表數據刷到硬盤上,之后復制MyISAM數據文件,最后釋放鎖。
備份MyISAM和InnoDB表最終會處于一致,在準備(prepare)過程結束后,InnoDB表數據已經前滾到整個備份結束的點,而不是回滾到xtrabackup剛開始時的點。這個時間點與執行FLUSH TABLES WITH READ LOCK
的時間點相同,所以MyISAM表數據與InnoDB表數據是同步的。類似Oracle的,InnoDB的prepare過程可以稱為recover(恢復),
MyISAM的數據復制過程可以稱為restore(還原)。
xtrabackup和innobackupex這兩個工具都提供了許多前文沒有提到的功能特點。手冊上有對各個功能都有詳細的介紹。簡單介紹下,這些工具提供了如流(streaming)備份,增量(incremental)備份等,
通過復制數據文件,復制日志文件和提交日志到數據文件(前滾)實現了各種復合備份方式。
實現細節:
XtraBackup以read-write模式打開innodb的數據文件,然后對其進行復制。其實它不會修改此文件。也就是說,運行 XtraBackup的用戶,必須對innodb的數據文件具有讀寫權限。
之所以采用read-write模式是因為XtraBackup采用了其內置的 innodb庫來打開文件,而innodb庫打開文件的時候就是rw的。
XtraBackup要從文件系統中復制大量的數據,所以它盡可能地使用posix_fadvise(),來告訴OS不要緩存讀取到的數據,從 而提升性能。因為這些數據不會重用到了,OS卻沒有這么聰明。
如果要緩存一下的話,幾個G的數據,會對OS的虛擬內存造成很大的壓力,其它進程,比如 mysqld很有可能被swap出去,這樣系統就會受到很大影響了。
在備份innodb page的過程中,XtraBackup每次讀寫1MB的數據,1MB/16KB=64個page。這個不可配置。讀1MB數據之后,XtraBackup一頁一頁地遍歷這1MB數據,使用innodb的buf_page_is_corrupted()
函數檢查此頁的數據是否正常, 如果數據不正常,就重新讀取這一頁,最多重新讀取10次,如果還是失敗,備份就失敗了,退出。在復制transactions log的時候,每次讀寫512KB的數據。
同樣不可以配置。