Percona XtraBackup 備份原理說明【轉】

本文來自:http://mysql.taobao.org/monthly/2016/03/07/mysql

前言

Percona XtraBackup(簡稱PXB)是 Percona 公司開發的一個用於 MySQL 數據庫物理熱備的備份工具,支持 MySQL(Oracle)、Percona Server 和 MariaDB,而且所有開源,真可謂是業界良心。咱們 RDS MySQL 的物理備份就是基於這個工具作的。nginx

項目的 blueprint 和 bug 討論放在 Launchpad,代碼以前也放在 Launchpad,如今已經遷移到 Github 啦,項目更新發布很是快,感興趣的能夠關注 :-)git

本文會介紹下備份工具的工做原理,但願對你們有所幫助。github

工具集

軟件包安裝完後一共有4個可執行文件,以下:sql

usr ├── bin │ ├── innobackupex │ ├── xbcrypt │ ├── xbstream │ └── xtrabackup 

其中最主要的是 innobackupex 和 xtrabackup,前者是一個 perl 腳本,後者是 C/C++ 編譯的二進制。數據庫

xtrabackup 是用來備份 InnoDB 表的,不能備份非 InnoDB 表,和 mysqld server 沒有交互;innobackupex 腳本用來備份非 InnoDB 表,同時會調用 xtrabackup 命令來備份 InnoDB 表,還會和 mysqld server 發送命令進行交互,如加讀鎖(FTWRL)、獲取位點(SHOW SLAVE STATUS)等。簡單來講,innobackupex 在 xtrabackup 之上作了一層封裝。架構

通常狀況下,咱們是但願能備份 MyISAM 表的,雖然咱們可能本身不用 MyISAM 表,可是 mysql 庫下的系統表是 MyISAM 的,所以備份基本都經過 innobackupex 命令進行;另一個緣由是咱們可能須要保存位點信息。併發

另外2個工具相對小衆些,xbcrypt 是加解密用的;xbstream 相似於tar,是 Percona 本身實現的一種支持併發寫的流文件格式。兩都在備份和解壓時都會用到(若是備份用了加密和併發)。app

本文的介紹的主角是 innobackupex 和 xtrabackup工具

原理

通訊方式

2個工具之間的交互和協調是經過控制文件的建立和刪除來實現的,主要文件有:

  • xtrabackup_suspended_1
  • xtrabackup_suspended_2
  • xtrabackup_log_copied

舉個栗子,咱們來看備份時 xtrabackup_suspended_2 是怎麼來協調2個工具進程的

  1. innobackupex 在啓動 xtrabackup 進程後,會一直等 xtrabackup 備份完 InnoDB 文件,方式就是等待 xtrabackup_suspended_2 這個文件被建立出來;
  2. xtrabackup 在備完 InnoDB 數據後,就在指定目錄下建立出這個文件,而後等這個文件被 innobackupex 刪除;
  3. innobackupex 檢測到文件 xtrabackup_suspended_2 被建立出來後,就繼續往下走;
  4. innobackupex 在備份完非 InnoDB 表後,刪除 xtrabackup_suspended_2 這個文件,這樣就通知 xtrabackup 能夠繼續了,而後等 xtrabackup_log_copied 被建立;
  5. xtrabackup 檢測到 xtrabackup_suspended_2 文件刪除後,就能夠繼續往下了。

是否是感受有點難以想象,經過文件是否存在來控制進程,這種方式很是的不靠譜,由於很是容易被外部干擾,好比文件被別人誤刪掉,或者2個正在跑的備份控制文件誤放在同一個目錄下,就等着備份亂掉吧,可是 Percona 就是這麼幹的。

之因此這麼搞,估計主要是由於 perl 和 C 二進制2個進程,沒有既好用又方便的通訊方式,搞個協議啥的太麻煩了。可是官方也以爲這種方式不靠譜,11年就搞了個 blueprint 要用C重寫 innobackupex,終於在2.3 版本實現了,innobackupex 功能所有集成到 xtrabackup 裏面,只有一個 binary,另外爲了使用上的兼容考慮,innobackupex做爲 xtrabackup 的一個軟鏈。對於二次開發來講,2.3 擺脫了以前2個進程協做的負擔,架構上明顯要好於以前版本。考慮到 perl + C 這種架構的長期存在,大多數讀者朋友也基本用的2.3以前版本,本文的介紹也是基於老的架構(2.2版本),可是原理和2.3是同樣的,只是實現上的差異。

備份過程

整個備份過程以下圖:


PXB 備份過程

  1. innobackupex 在啓動後,會先 fork 一個進程,啓動 xtrabackup進程,而後就等待 xtrabackup 備份完 ibd 數據文件;
  2. xtrabackup 在備份 InnoDB 相關數據時,是有2種線程的,1種是 redo 拷貝線程,負責拷貝 redo 文件,1種是 ibd 拷貝線程,負責拷貝 ibd 文件;redo 拷貝線程只有一個,在 ibd 拷貝線程以前啓動,在 ibd 線程結束後結束。xtrabackup 進程開始執行後,先啓動 redo 拷貝線程,從最新的 checkpoint 點開始順序拷貝 redo 日誌;而後再啓動 ibd 數據拷貝線程,在 xtrabackup 拷貝 ibd 過程當中,innobackupex 進程一直處於等待狀態(等待文件被建立)。
  3. xtrabackup 拷貝完成idb後,通知 innobackupex(經過建立文件),同時本身進入等待(redo 線程仍然繼續拷貝);
  4. innobackupex 收到 xtrabackup 通知後,執行FLUSH TABLES WITH READ LOCK (FTWRL),取得一致性位點,而後開始備份非 InnoDB 文件(包括 frm、MYD、MYI、CSV、opt、par等)。拷貝非 InnoDB 文件過程當中,由於數據庫處於全局只讀狀態,若是在業務的主庫備份的話,要特別當心,非 InnoDB 表(主要是MyISAM)比較多的話整庫只讀時間就會比較長,這個影響必定要評估到。
  5. 當 innobackupex 拷貝完全部非 InnoDB 表文件後,通知 xtrabackup(經過刪文件) ,同時本身進入等待(等待另外一個文件被建立);
  6. xtrabackup 收到 innobackupex 備份完非 InnoDB 通知後,就中止 redo 拷貝線程,而後通知 innobackupexredo log 拷貝完成(經過建立文件);
  7. innobackupex 收到 redo 備份完成通知後,就開始解鎖,執行 UNLOCK TABLES
  8. 最後 innobackupex 和 xtrabackup 進程各自完成收尾工做,如資源的釋放、寫備份元數據信息等,innobackupex 等待 xtrabackup 子進程結束後退出。

在上面描述的文件拷貝,都是備份進程直接經過操做系統讀取數據文件的,只在執行 SQL 命令時和數據庫有交互,基本不影響數據庫的運行,在備份非 InnoDB 時會有一段時間只讀(若是沒有MyISAM表的話,只讀時間在幾秒左右),在備份 InnoDB 數據文件時,對數據庫徹底沒有影響,是真正的熱備。

InnoDB 和非 InnoDB 文件的備份都是經過拷貝文件來作的,可是實現的方式不一樣,前者是以page爲粒度作的(xtrabackup),後者是 cp 或者 tar 命令(innobackupex),xtrabackup 在讀取每一個page時會校驗 checksum 值,保證數據塊是一致的,而 innobackupex 在 cp MyISAM 文件時已經作了flush(FTWRL),磁盤上的文件也是完整的,因此最終備份集裏的數據文件都是寫入完整的。

增量備份

PXB 是支持增量備份的,可是隻能對 InnoDB 作增量,InnoDB 每一個 page 有個 LSN 號,LSN 是全局遞增的,page 被更改時會記錄當前的 LSN 號,page中的 LSN 越大,說明當前page越新(最近被更新)。每次備份會記錄當前備份到的LSN(xtrabackup_checkpoints 文件中),增量備份就是隻拷貝LSN大於上次備份的page,比上次備份小的跳過,每一個 ibd 文件最終備份出來的是增量 delta 文件。

MyISAM 是沒有增量的機制的,每次增量備份都是所有拷貝的。

增量備份過程和全量備份同樣,只是在 ibd 文件拷貝上有不一樣。

恢復過程

若是看恢復備份集的日誌,會發現和 mysqld 啓動時很是類似,其實備份集的恢復就是相似 mysqld crash後,作一次 crash recover。

恢復的目的是把備份集中的數據恢復到一個一致性位點,所謂一致就是指原數據庫某一時間點各引擎數據的狀態,好比 MyISAM 中的數據對應的是 15:00 時間點的,InnoDB 中的數據對應的是 15:20 的,這種狀態的數據就是不一致的。PXB 備份集對應的一致點,就是備份時FTWRL的時間點,恢復出來的數據,就對應原數據庫FTWRL時的狀態。

由於備份時 FTWRL 後,數據庫是處於只讀的,非 InnoDB 數據是在持有全局讀鎖狀況下拷貝的,因此非 InnoDB 數據自己就對應 FTWRL 時間點;InnoDB 的 ibd 文件拷貝是在 FTWRL 前作的,拷貝出來的不一樣 ibd 文件最後更新時間點是不同的,這種狀態的 ibd 文件是不能直接用的,可是 redo log 是從備份開始一直持續拷貝的,最後的 redo 日誌點是在持有 FTWRL 後取得的,因此最終經過 redo 應用後的 ibd 數據時間點也是和 FTWRL 一致的。

因此恢復過程只涉及 InnoDB 文件的恢復,非 InnoDB 數據是不動的。備份恢復完成後,就能夠把數據文件拷貝到對應的目錄,而後經過mysqld來啓動了。

相關文章
相關標籤/搜索