MySQL-物理備份-Percona XtraBackup 備份原理

Percona XtraBackup簡稱PXB)是 Percona 公司開發的一個用於 MySQL 數據庫物理熱備的備份工具,支持 MySQl(Oracle)、Percona Server 和 MariaDB,並且全部開源,真可謂是業界良心。

工具集
軟件包安裝完後一共有4個可執行文件,如下:
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 自己實現的一種支持併發寫的流文件格式。兩都在備份和解壓時都會用到(如果備份用了加密和併發)。

本文的介紹的主角是 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來啓動了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章