ch5 MySQL 備份與恢復

5 MySQL 備份與恢復

前言 node

數據庫的備份與恢復一直都是 DBA 工做中最爲重要的部分之一,也是基本工做之一。任何正式環境的數據庫都必須有完整的備份計劃和恢復測試,本章內容將主要介紹 MySQL 數據庫的備份與恢復相關內容。 mysql

5.1 數據庫備份使用場景

你真的明白了本身所作的數據庫備份是要面對什麼樣的場景的嗎? 正則表達式

我想任何一位維護過數據庫的人都知道數據庫是須要備份的,也知道備份數據庫是數據庫維護必不可少的一件事情。那麼是否每個人都知道本身所作的備份究竟是爲了應對哪些場景的呢?抑或者說咱們每一個人是否都很清楚的知道,爲何一個數據庫須要做備份呢?讀到這裏,我想不少讀者朋友都會嗤之以鼻,"備份的做用不就是爲了防止原數據丟失嗎,這誰不知道?"。確實,數據庫的備份很大程度上的做用,就是當咱們的數據庫由於某些緣由而形成部分或者所有數據丟失後,方便找回丟失的數據。可是,不一樣類型的數據庫備份,所能應付狀況是不同的,並且,數據庫的備份同時也還具備其餘不少的做用。並且我想,每一個人對數據庫備份的做用的理解可能都會有部分區別。 sql

下面我就列舉一下我我的理解的咱們可以須要用到數據庫備份的一些比較常見的狀況吧。 數據庫

1、數據丟失應用場景 安全

一、人爲操做失誤形成某些數據被誤操做; 二、軟件 BUG 形成數據部分或者所有丟失; 服務器

  1. 硬件故障形成數據庫數據部分或所有丟失;
  2. 安全漏洞被入侵數據被惡意破壞;

2、非數據丟失應用場景 session

  1. 特殊應用場景下基於時間點的數據恢復;
  2. 開發測試環境數據庫搭建;
  3. 相同數據庫的新環境搭建;
  4. 數據庫或者數據遷移;

上面所列出的只是一些常見的應用場景而已,除了上面這幾種場景外,數據庫備份還會有不少其餘應用場景,這裏就不一一列舉了。那麼各位讀者過曾經或是如今所作的數據庫備份究竟是爲了應對以上哪種(或者幾種)場景?或者說,咱們所作的數據庫備份可以應對以上哪幾種應用場景?不知道這個問題你們是否有考慮過。 工具

咱們必須認可,沒有哪種數據庫備份可以解決全部以上列舉的幾種常見應用場景,即便僅僅只是數據丟失的各類場景都沒法經過某一種數據庫備份完美的解決,固然也就更不用說可以解決全部的備份應用場景了。 測試

好比當咱們遇到磁盤故障,丟失了整個數據庫的全部數據,而且沒法從已經出現故障的硬盤上面恢復出來的時候,咱們可能必須經過一個實時或者有短暫時間差的複製備份數據庫存在。固然若是沒有這樣的一個數據庫,就必需要有最近時間的整個數據庫的物理或者邏輯備份數據,而且有該備份以後的全部物理或者邏輯增量備份,以指望儘量將數據恢復到出現故障以前最近的時間點。而當咱們遇到認爲操做失誤形成數據被誤操做以後,咱們須要有一個能恢復到錯誤操做時間點以前的瞬間的備份存在,固然這個備份多是整個數據庫的備份,也能夠僅僅只是被誤操做的表的備份。而當咱們要作跨平臺的數據庫遷移的時候,咱們所須要的又只能是一個邏輯的數據庫備份,由於平臺的差別可能使物理備份的文件格式在兩個平臺上沒法兼容。

既然沒有哪種不少中數據庫備份可以完美的解決全部的應用場景,而每一個數據庫環境所須要面對的數據庫備份應用場景又可能各不同,可能只是須要面對不少種場景中的某一種或幾種,那麼咱們就很是有必要指定一個合適的備份方案和備份策略,經過最簡單的技術和最低廉的成本,來知足咱們的需求。

5.2 邏輯備份與恢復測試

5.2.1 什麼樣的備份是數據庫邏輯備份呢?

你們都知道,數據庫在返回數據給咱們使用的時候都是按照咱們最初所設計指望的具備必定邏輯關聯格式的形式一條一條數據來展示的,具備必定的商業邏輯屬性,而在物理存儲的層面上數據庫軟件倒是按照數據庫軟件所設計的某種特定格式通過必定的處理後存放。

數據庫邏輯備份就是備份軟件按照咱們最初所設計的邏輯關係,以數據庫的邏輯結構對象爲單位,將數據庫中的數據按照預約義的邏輯關聯格式一條一條生成相關的文本文件,以達到備份的目的。

5.2.2 經常使用的邏輯備份

邏輯備份能夠說是最簡單,也是目前中小型系統最常使用的備份方式。在 MySQL 中咱們經常使用的邏輯備份主要就是兩種,一種是將數據生成能夠徹底重現當前數據庫中數據的 INSERT 語句,另一種就是將數據經過邏輯備份軟件,將咱們數據庫表數據以特定分隔符進行分隔後記錄在文本文件中。

一、生成 INSERT 語句備份

兩種邏輯備份各有優劣,所針對的使用場景也會稍有差異,咱們先來看一下生成 INSERT 語句的邏輯備份。

在 MySQL 數據庫中,咱們通常都是經過 MySQL 數據庫軟件自帶工具程序中的 mysqldump 來實現聲稱 INSERT 語句的邏輯備份文件。其使用方法基本以下:

    Dumping    definition    and    data    mysql    database    or    table

    Usage:    mysqldump    [OPTIONS]    database    [tables]

    OR    mysqldump    [OPTIONS]    --databases    [OPTIONS]    DB1    [DB2    DB3...]

    OR    mysqldump    [OPTIONS]    --all-databases [OPTIONS]

因爲 mysqldump 的使用方法比較簡單,大部分須要的信息均可以經過運行"mysqldump    -help"而得到。這裏我只想結合 MySQL 數據庫的一些概念原理和你們探討一下當咱們使用 mysqldump 來作數據庫邏輯備份的時候有些什麼技巧以及須要注意一些什麼內容。

咱們都知道,對於大多數使用數據庫的軟件或者網站來講,都但願本身數據庫可以提供儘量高的可用性,而不是時不時的就須要停機中止提供服務。由於一旦數據庫沒法提供服務,系統就沒法再經過存取數據來提供一些動態功能。因此對於大多數系統來講若是要讓每次備份都停機來作可能都是不可接受的,但是 mysqldump 程序的實現原理是經過咱們給的參數信息加上數據庫中的系統表信息來一個表一個表獲取數據而後生成 INSERT 語句再寫入備份文件中的。這樣就出現了一個問題,在系統正常運行過程當中,極可能會不斷有數據變動的請求正在執行,這樣就可能形成在 mysqldump 備份出來的數據不一致。也就是說備份數據極可能不是同一個時間點的數據,並且甚至可能都沒辦法知足完整性約束。這樣的備份集對於有些系統來講可能並無太大問題,可是對於有些對數據的一致性和完整性要求比較嚴格系統來講問題就大了,就是一個徹底無效的備份集。

對於如此場景,咱們該如何作?咱們知道,想數據庫中的數據一致,那麼只有兩種狀況下能夠作到。

第1、同一時刻取出全部數據;第2、數據庫中的數據處於靜止狀態。

對於第一種狀況,你們確定會想,這可能嗎?無論如何,只要有兩個以上的表,就算咱們如何寫程序,都不可能昨晚徹底一致的取數時間點啊。是的,咱們確實沒法經過常規方法讓取數的時間點徹底一致,可是你們不要忘記,在同一個事務中,數據庫是能夠作到所讀取的數據是處於同一個時間點的。因此,對於事務支持的存儲引擎,如 Innodb 或者 BDB 等 ,咱們就能夠經過控制將整個備份過程控制在同一個事務中,來達到備份數據的一致性和完整性,並且 mysqldump 程序也給咱們提供了相關的參數選項來支持該功能,就是經過 "-single-transaction"選項,能夠不影響數據庫的任何正常服務。

對於第二種狀況我想你們首先想到的確定是將須要備份的表鎖定,只容許讀取而不容許寫入。是的,咱們確實只能這麼作。咱們只能經過一個折衷的處理方式,讓數據庫在備份過程當中僅提供數據的查詢服務,鎖定寫入的服務,來使數據暫時處於一個一致的不會被修改的狀態,等 mysqldump 完成備份後再取消寫入鎖定,從新開始提供完整的服務。mysqldump 程序本身也提供了相關選項如"--lock-tables"和"--lock-all-tables",在執行以前會鎖定表,執行結束後自動釋放鎖定。這裏有一點須要注意的就是,"--lock-tables"並非一次性將須要 dump 的全部表鎖定,而是每次僅僅鎖定一個數據庫的表,若是你須要 dump 的表分別在多個不一樣的數據庫中,必定要使用"--lock-all-tables"才能確保數據的一致完整性。

當經過 mysqldump 生成 INSERT 語句的邏輯備份文件的時候,有一個很是有用的選項能夠供咱們使用,那就是"--master-data[=value]"。當添加了"--master-data=1"的時候, mysqldump 會將當前 MySQL 使用到 binlog 日誌的名稱和位置記錄到 dump 文件中,而且是被以 CHANGE_MASTER 語句的形式記錄,若是僅僅只是使用"--master-data"或者"--masterdata=2",則 CHANGE_MASTER 語句會以註釋的形式存在。這個選項在實施 slave 的在線搭建的時候是很是有用的,即便不是進行在線搭建 slave,也能夠在某些狀況下作恢復的過程當中經過備份的 binlog 作進一步恢復操做。

在某些場景下,咱們可能只是爲了將某些特殊的數據導出到其餘數據庫中,而又不但願經過先建臨時表的方式來實現,咱們還能夠在經過 mysqldump 程序的"—where='wherecondition'"來實現,但只能在僅 dump 一個表的狀況下使用。

其實除了以上一些使用訣竅以外,mysqldump 還提供了其餘不少有用的選項供你們在不一樣的場景下只用,如經過"--no-data"僅僅 dump 數據庫結構建立腳本,經過"--no-createinfo"去掉 dump 文件中建立表結構的命令等等,感興趣的讀者朋友能夠詳細閱讀 mysqldump 程序的使用介紹再自行測試。

二、生成特定格式的純文本備份數據文件備份

除了經過生成 INSERT 命令來作邏輯備份以外,咱們還能夠經過另一種方式將數據庫中的數據以特定分隔字符將數據分隔記錄在文本文件中,以達到邏輯備份的效果。這樣的備份數據與 INSERT 命令文件相比,所須要使用的存儲空間更小,數據格式更加清晰明確,編輯方便。可是缺點是在同一個備份文件中不能存在多個表的備份數據,沒有數據庫結構的重建命令。對於備份集須要多個文件,對咱們產生的影響無非就是文件多了維護和恢復成本增長,但這些基本上均可以經過編寫一些簡單的腳原本實現

那咱們通常可使用什麼方法來生成這樣的備份集文件呢,其實 MySQL 也已經給咱們實現的相應的功能。

在 MySQL 中通常都使用如下兩種方法來得到能夠自定義分隔符的純文本備份文件。

    一、經過執行 SELECT    ...    TO    OUTFILE    FROM    ...命令來實現

在 MySQL 中提供了一種 SELECT 語法,專供用戶經過 SQL 語句將某些特定數據以指定格式輸出到文本文件中,同時也提供了實用工具和相關的命令能夠方便的將導出文件原樣再導入到數據庫中。正不正是咱們作備份所須要的麼?

該命令有幾個須要注意的參數以下:

實現字符轉義功能的"FIELDS ESCAPED BY ['name']" 將 SQL 語句中須要轉義的字符進行轉義;

    能夠將字段的內容"包裝"起來的"FIELDS    [OPTIONALLY]    ENCLOSED    BY    'name'",如

果不使用"OPTIONALLY"則包括數字類型的全部類型數據都會被"包裝",使 用"OPTIONALLY" 以後,則數字類型的數據不會被指定字符"包裝"。

經過"FIELDS    TERMINATED    BY"能夠設定每兩個字段之間的分隔符;而經過"LINES    TERMINATED    BY"則會告訴 MySQL 輸出文件在每條記錄結束的時候須要

添加什麼字符。

如如下示例:

    root@localhost :    test    10:02:02>    SELECT    *    INTO    OUTFILE    '/tmp/dump.text'

    ->    FIELDS    TERMINATED    BY    ','    OPTIONALLY    ENCLOSED    BY    '"'

    ->    LINES    TERMINATED    BY    '\n'

->    FROM    test_outfile    limit    100; Query    OK,    100    rows    affected    (0.00    sec)

root@localhost :    test    10:02:11>    exit Bye root@sky:/tmp# cat    dump.text

350021,21,"A","abcd"

350022,22,"B","abcd"

350023,23,"C","abcd"

350024,24,"D","abcd"

350025,25,"A","abcd" ...    ...

二、經過 mysqldump 導出可能咱們都知道 mysqldump 能夠將數據庫中的數據以 INSERT 語句的形式生成相關備份文件,其實除了生成 INSERT 語句以外,mysqldump 還一樣能實現上面"SELECT ... TO

OUTFILE    FROM    ..."所實現的功能,並且同時還會生成一個相關數據庫結構對應的建立腳本 。

如如下示例:

root@sky:~# ls -l /tmp/mysqldump total 0 root@sky:~# mysqldump -uroot -T/tmp/mysqldump test test_outfile --fields-

enclosed-by=\" --fields-terminated-by=, root@sky:~# ls -l /tmp/mysqldump total 8

    -rw-r--r--    1    root    root    1346    2008-10-14    22:18    test_outfile.sql

    -rw-rw-rw-    1    mysql    mysql    2521    2008-10-14    22:18    test_outfile.txt

    root@sky:~#    cat    /tmp/mysqldump/test_outfile.txt

350021,21,"A","abcd"

350022,22,"B","abcd"

350023,23,"C","abcd"

350024,24,"D","abcd"

350025,25,"A","abcd" ...    ...

    root@sky:~#    cat    /tmp/mysqldump/test_outfile.sql

    --    MySQL    dump    10.11

--

    --    Host:    localhost    Database:    test

--    -------------------------------------------------------    Server    version    5.0.51a-log

    /*!40101    SET    @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;

    /*!40101    SET    @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;

    /*!40101    SET    @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;

    /*!40101    SET    NAMES    utf8    */;

    /*!40103    SET    @OLD_TIME_ZONE=@@TIME_ZONE    */;

    /*!40103    SET    TIME_ZONE='+00:00'    */;

    /*!40101    SET    @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=''    */;

    /*!40111    SET    @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0    */;

--

--    Table    structure    for    table    `test_outfile` --

    DROP    TABLE    IF    EXISTS    `test_outfile`;

    SET    @saved_cs_client    =    @@character_set_client;

    SET    character_set_client =    utf8;

    CREATE    TABLE    `test_outfile` (

    `id`    int(11)    NOT    NULL    default    '0',

    `t_id`    int(11)    default    NULL,

    `a`    char(1)    default    NULL,

    `mid`    varchar(32)    default    NULL

    )    ENGINE=MyISAM DEFAULT    CHARSET=utf8;

    SET    character_set_client =    @saved_cs_client;

    /*!40103    SET    TIME_ZONE=@OLD_TIME_ZONE    */;

    /*!40101    SET    SQL_MODE=@OLD_SQL_MODE */;

    /*!40101    SET    CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

    /*!40101    SET    CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;

/*!40101    SET    COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111    SET    SQL_NOTES=@OLD_SQL_NOTES */;

    --    Dump    completed    on    2008-10-14    14:18:23

這樣的輸出結構對咱們作爲備份來使用是很是合適的,固然若是一次有多個表須要被 dump,就會針對每一個表都會生成兩個相對應的文件。

5.2.3 邏輯備份恢復方法

僅僅有了備份仍是不夠啊,咱們得知道如何去使用這些備份,如今咱們就看看上面所作的邏輯備份的恢復方法:

因爲全部的備份數據都是以咱們最初數據庫結構的設計相關的形式所存儲,因此邏輯備份的恢復也相對比較簡單。固然,針對兩種不一樣的邏輯備份形式,恢復方法也稍有區別。下面咱們就分別針對這兩種邏輯備份文件的恢復方法作一個簡單的介紹。

  1. INSERT 語句文件的恢復:

對於 INSERT 語句形式的備份文件的恢復是最簡單的,咱們僅僅只須要運行該備份文件中的全部(或者部分)SQL 命令便可。首先,若是須要作徹底恢復,那麼咱們能夠經過使用 "mysql < backup.sql"直接調用備份文件執行其中的全部命令,將數據徹底恢復到備份時候的狀態。若是已經使用 mysql 鏈接上了 MySQL,那麼也能夠經過在 mysql 中執行"source

/path/backup.sql"或者"\.    /path/backup.sql"來進行恢復。

  1. 純數據文本備份的恢復:

若是是上面第二中形式的邏輯備份,恢復起來會稍微麻煩一點,須要一個表一個表經過相關命令來進行恢復,固然若是經過腳原本實現自動多表恢復也是比較方便的。恢復方法也有兩個,一是經過 MySQL 的"LOAD    DATA    INFILE"命令來實現,另外一種方法就是經過 MySQL 提供的使用工具 mysqlimport 來進行恢復。

邏輯備份能作什麼?不能作什麼?

在清楚瞭如何使用邏輯備份進行相應的恢復以後,咱們須要知道咱們能夠利用這些邏輯備份作些什麼。

  1. 經過邏輯備份,咱們能夠經過執行相關 SQL 或者命令將數據庫中的相關數據徹底恢復到備份時候所處的狀態,而不影響不相關的數據;
  2. 經過全庫的邏輯備份,咱們能夠在新的 MySQL 環境下徹底重建出一個於備份時候徹底同樣的數據庫,而且不受 MySQL 所處的平臺類型限制;
  3. 經過特定條件的邏輯備份,咱們能夠將某些特定數據輕鬆遷移(或者同步)到其餘的 MySQL 或者另外的數據庫環境;
  4. 經過邏輯備份,咱們能夠僅僅恢復備份集中的部分數據而不須要所有恢復。

    在知道了邏輯備份能作什麼以後,咱們必須還要清楚他不能作什麼,這樣咱們本身才能清楚的知道這樣的一個備份可否知足本身的預期,是否確實是本身想要的。

    1. 邏輯備份沒法讓數據恢復到備份時刻之外的任何一個時刻;
    2. 邏輯備份沒法

5.2.4    邏輯備份恢復測試

時有聽到某某的數據庫出現問題,而當其信心十足的準備拿以前所作好的數據庫進行恢復的時候才發現本身的備份集不可用,或者並不能達到本身作備份時候所預期的恢復效果。遇到這種情景的時候,恐怕每一個人都會鬱悶至極的。數據庫備份最重要最關鍵的一個用途就是當咱們的數據庫出現某些異常情況,須要對數據進行恢復的時候使用的。做爲一個維護人員,咱們是絕對不該該出現此類低級錯誤的。那咱們到底該如何避免此類問題呢?只有一個辦法,那就是週期性的進行模擬恢復測試,校驗咱們的備份集是否真的有效,是否確實可以按照咱們的備份預期進行相應的恢復。

到這裏可能有人會問,恢復測試又該如何作呢,咱們總不能真的將線上環境的數據進行恢復啊?是的,線上環境的數據確實不能被恢復,可是咱們爲何不能在測試環境或者其餘的地方作呢?作恢復測試只是爲了驗證咱們的備份是否有效,是否能達到咱們的預期。因此在作恢復測試以前咱們必定要先清楚的知道咱們所作的備份究竟是爲了應用於什麼樣的場景的。就好比咱們作了一個全庫的邏輯備份,目的多是爲了當數據庫出現邏輯或者物理異常的時候可以恢復整個數據庫的數據到備份時刻,那麼咱們惡的恢復測試就只須要將整個邏輯備份進行全庫恢復,看是否可以成功的重建一個完整的數據庫。至於恢復的數據是否和備份時刻一致,就只能依靠咱們本身來人工判斷比較。此外咱們可能還但願當某一個數據庫對象,好比某個表出現問題以後可以儘快的恢復該表數據到備份時刻。那麼咱們就能夠針對單個指定表進行抽樣恢復測試。

下面咱們就假想數據庫主機崩潰,硬件損壞,形成數據庫數據所有丟失,來作一次全庫恢復的測試示例:

當咱們的數據庫出現硬件故障,數據所有丟失以後,咱們必須儘快找到一臺新的主機以頂替損壞的主機來恢復相應的服務。在恢復服務以前,咱們首先須要重建損壞的數據庫。假設咱們已經拿到了一臺新的主機,MySQL 軟件也已經安裝就位,相關設置也都已經調整好,就等着恢復數據庫了。

咱們須要取回離崩潰時間最近的一次全庫邏輯備份文件,複製到準備的新主機上,啓動已經安裝好的 MySQL。

因爲咱們有兩種邏輯備份格式,每種格式的恢復方法並不同,因此這裏將對兩種格式的邏輯備份的恢復都進行示例。

一、若是是 INSERT 語句的邏輯備份

  1. 準備好備份文件,copy 到某特定目錄,如"/tmp"下;
  2. 經過執行以下命令執行備份集中的相關命令:mysql    -uusername    -p    <    backup.sql

或者先經過 mysql 登陸到數據庫中,而後再執行以下命令:

    root@localhost :    (none)    09:59:40>    source    /tmp/backup.sql

  1. 再到數據庫中檢查相應的數據庫對象,看是否已經齊全;d、抽查幾個表中的數據進行人工校驗,並通知開啓應用內部測試校驗,當全部校驗都經過以後,便可對外提供服務了。

固然上面所說的步驟都是在默認每一步都正常的前提下進行的,若是發現某一步有問題。倘若在 b 步驟出現異常,沒法繼續進行下去,咱們首先須要根據出現的錯誤來排查是不是咱們恢復命令有錯?是否咱們的環境有問題等?等等。若是咱們確認是備份文件的問題,那麼說明咱們的這個備份是無效的,說明測試失敗了。若是咱們恢復過程很正常,可是在校驗的時候發現缺乏數據庫對象,或者某些對象中的數據不正確,或者根本沒有數據。一樣說明咱們的備份級沒法知足預期,備份失敗。固然,若是咱們是在實際工做的恢復過程當中遇到相似狀況的時候,若是還有更早的備份集,咱們必須退一步使用更早的備份集作相同的恢復操做。雖然更早的備份集中的數據可能會有些失真,可是至少能夠部分恢復,而不至於丟失全部數據。

二、若是咱們是備份的以特殊分隔符分隔的純數據文本文件 a、第一步和 INSERT 備份文件沒有區別,就是將最接近崩潰時刻的備份文件準備好;

b、經過特定工具或者命令將數據導入如到數據庫中:

因爲數據庫結構建立腳本和純文本數據備份文件分開存放,因此咱們首先須要執行數據庫結構建立腳本,而後再導入數據。結構建立腳本的方法和上面第一種備份的恢復測試中的 b 步驟徹底同樣。

有了數據庫結構以後,咱們就能夠導入備份數據了,以下:

mysqlimport --user=name --password=pwd test --fields-enclosed-by=\" -fields-terminated-by=, /tmp/test_outfile.txt 或者

    LOAD    DATA    INFILE    '/tmp/test_outfile.txt'    INTO    TABLE    test_outfile    FIELDS

TERMINATED    BY    '"'    ENCLOSED    BY    ',';

後面的步驟就和備份文件爲 INSERT 語句備份的恢復徹底同樣了,這裏就再也不累述。

5.3 物理備份與恢復測試

前面一節咱們瞭解瞭如何使用 MySQL 的邏輯備份,並作了一個簡單的邏輯備份恢復示例,在這一節咱們再一塊兒瞭解一些 MySQL 的物理備份。

5.3.1 什麼樣的備份是數據庫物理課備份

在瞭解 MySQL 的物理備份以前,咱們須要先了解一下,什麼是數據庫物理備份?既然是物理備份,那麼確定是和數據庫的物理對象相對應的。就如同邏輯備份根據由咱們根據業務邏輯所設計的數據庫邏輯對象所作的備份同樣,數據庫的物理備份就是對數據庫的物理對象所作的備份。數據庫的物理對象主要由數據庫的物理數據文件、日誌文件以及配置文件等組成。在 MySQL 數據庫中,除了 MySQL 系統共有的一些日誌文件和系統表的數據文件以外,每一種存儲引擎本身還會有不太同樣的物理對象,在以前第一篇的"MySQL 物理文件組成"中咱們已經有了一個基本的介紹,在下面咱們將詳細列出幾種經常使用的存儲引擎各自所對應的物理對象(物理文件),以便在後面你們可以清楚的知道各類存儲引擎在作物理備份的時候到底哪些文件是須要備份的哪些又是不須要備份的。

5.3.2 MySQL 物理備份所需文件

MyISAM 存儲引擎

MyISAM 存儲引擎的全部數據都存放在 MySQL 配置中所設定的"datadir"目錄下。實際上無論咱們使用的是 MyISAM 存儲引擎仍是其餘任何存儲引擎,每個數據庫都會在 "datadir"目錄下有一個文件夾(包括系統信息的數據庫 mysql 也是同樣)。在各個數據庫中每個 MyISAM 存儲引擎表都會有三個文件存在,分別爲記錄表結構元數據的".frm"文件,存儲表數據的".MYD"文件,以及存儲索引數據的".MYI"文件。因爲 MyISAM 屬於非事務性存儲引擎,因此他沒有本身的日誌文件。因此 MyISAM 存儲引擎的物理備份,除了備份 MySQL 系統的共有物理文件以外,就只須要備份上面的三種文件便可。

Innodb 存儲引擎

Innodb 存儲引擎屬於事務性存儲引擎,並且存放數據的位置也可能與 MyISAM 存儲引擎有所不一樣,這主要取決於咱們對 Innodb 的""相關配置所決定。決定 Innodb 存放數據位置的 配 置 爲 " innodb_data_home_dir " 、 " innodb_data_file_path " 和 "innodb_log_group_home_dir"這三個目錄位置指定參數,以及另一個決定 Innodb 的表空間存儲方式的參數"innodb_file_per_table"。前面三個參數指定了數據和日誌文件的存放位置,最後一個參數決定 Innodb 是以共享表空間存放數據仍是以獨享表空間方式存儲數據。這幾個參數的相關使用說明咱們已經在第一篇的"MySQL 存儲引擎介紹"中作了相應的解釋,在 MySQL 的官方手冊中也有較爲詳細的說明,因此這裏就再也不累述了。

    如 果 我 們 使 用 了 共 享 表 空 間 的 存 儲 方 式 , 那 麼    Innodb    需 要 備 份 備 份

"innodb_data_home_dir"和"innodb_data_file_path"參數所設定的全部數據文件,

"datadir"中相應數據庫目錄下的全部 Innodb 存儲引擎表的".frm"文件;

而若是咱們使用了獨享表空間,那麼咱們除了備份上面共享表空間方式所須要備份的全部文件以外,咱們還須要備份"datadir"中相應數據庫目錄下的全部".idb"文件,該文件中存放的纔是獨享表空間方式下 Innodb 存儲引擎表的數據。可能在這裏有人文,既然是使用獨享表空間,那咱們爲何還要備份共享表空間"才使用到"的數據文件呢?其實這是不少人的一個共性誤區,覺得使用獨享表空間的時候 Innodb 的全部信息就都存放在 "datadir"所設定數據庫目錄下的".ibd"文件中。實際上並非這樣的,".ibd"文件中所存放的僅僅只是咱們的表數據而已,你們都很清楚,Innodb 是事務性存儲引擎,他是須要 undo 和 redo 信息的,而無論 Innodb 使用的是共享仍是獨享表空間的方式來存儲數據,與事務相關的 undo 信息以及其餘的一些元數據信息,都是存放在"innodb_data_home_dir" 和"innodb_data_file_path"這兩個參數所設定的數據文件中的。因此要想 Innodb 的物理備 份 有 效 ,"innodb_data_home_dir"和"innodb_data_file_path"參數所設定的數據文件無論在什麼狀況下咱們都必須備份。

此外,除了上面所說的數據文件以外,Innodb 還有本身存放 redo 信息和相關事務信息的日誌文件在"innodb_log_group_home_dir"參數所設定的位置。因此要想 Innodb 物理備份可以有效使用,咱們還比須要備份"innodb_log_group_home_dir"參數所設定的位置的全部日誌文件。

NDB    Cluster 存儲引擎

NDB Cluster 存儲引擎(其實也能夠說是 MySQL Cluster)的物理備份須要備份的文件主要有一下三類:

  1. 元數據(Metadata):包含全部的數據庫以及表的定義信息;
  2. 表數據(Table    Records):保存實際數據的文件;
  3. 事務日誌數據(Transaction    Log):維持事務一致性和完整性,以及恢復過程當中所須要的事務信息。

不管是經過停機冷備份,仍是經過    NDB    Cluster    自行提供的在線聯機備份工具,或者是第三方備份軟件來進行備份,都須要備份以上三種物理文件才能構成一個完整有效的備份集。固然,相關的配置文件,尤爲是管理節點上面的配置信息,一樣也須要備份。

5.3.3 各存儲引擎經常使用物理備份方法

因爲不一樣存儲引擎所須要備份的物理對象(文件)並不同,且每一個存儲引擎對數據文件的一致性要求也不同因此各個存儲引擎在進行物理備份的時候所使用的備份方法也有區別。固然,若是咱們是要作冷備份(停掉數據庫以後的備份),咱們所須要作的事情都很簡單,那就是直接 copy 全部數據文件和日誌文件到備份集須要存放的位置便可,無論是何種存儲引擎均可以這樣作。因爲冷備份方法簡單,實現容易,因此這裏就不詳細說明了。

在咱們的實際應用環境中,是不多有可以讓咱們能夠停機作平常備份的狀況的,咱們只能在數據庫提供服務的狀況下來完成數據庫備份。這也就是咱們俗稱的熱物理備份了。下面咱們就針對各個存儲引擎單獨說明各自最經常使用的在線(熱)物理備份方法。

MyISAM 存儲引擎

上面咱們介紹了 MyISAM 存儲引擎文件的物理文件比較集中,並且不支持事務沒有 redo 和 undo 日誌,對數據一致性的要求也並非特別的高,因此 MyISAM 存儲引擎表的物理備份也比較簡單,只要將 MyISAM 的物理文件 copy 出來便可。可是,雖然 MyISAM 存儲引擎沒有事務支持,對數據文件的一致性要求沒有 Innodb 之類的存儲引擎那麼嚴格,可是 MyISAM 存儲引擎的同一個表的數據文件和索引文件之間是有一致性要求的。當 MyISAM 存儲引擎發現某個表的數據文件和索引文件不一致的時候,會標記該表處於不可用狀態,並要求你進行修復動做,固然,通常狀況下的修復都會比較容易。可是,即便數據庫存儲引擎自己對數據文件的一致性要求並非很苛刻,咱們的應用也容許數據不一致嗎?我想答案確定是否認的,因此咱們本身必須至少保證數據庫在備份時候的數據是處於某一個時間點的,這樣就要求咱們必須作到在備份 MyISAM 數據庫的物理文件的時候讓 MyISAM 存儲引擎中止寫操做,僅僅提供讀服務,其根本實質就是給數據庫表加鎖來阻止寫操做。

MySQL 本身提供了一個使用程序 mysqlhotcopy,這個程序就是專門用來備份 MyISAM 存儲引擎的。不過若是你有除了 MyISAM 以外的其餘非事務性存儲引擎,也能夠經過合適的參數設置,或者微調該備份腳本,也都能經過 mysqlhotcopy 程序來完成相應的備份任務,基本用法以下:

    mysqlhotcopy    db_name[./table_regex/] [new_db_name    |    directory]

從上面的基本使用方法咱們能夠看到,mysqlhotcopy 出了能夠備份整個數據庫,指定的某個表,還能夠經過正則表達式來匹配某些表名來針對性的備份某些表。備份結果就是指定數據庫的文件夾下包括全部指定的表的相應物理文件。

mysqlhotcopy 是一個用 perl 編寫的使用程序,其主要實現原理實際上就是經過先 LOCK 住表,而後執行 FLUSH    TABLES 動做,該正常關閉的表正常關閉,將該 fsync 的數據都 fsync,而後經過執行 OS 級別的複製(cp 等)命令,將須要備份的表或者數據庫的全部物理文件都複製到指定的備份集位置。

此外,咱們也能夠經過登陸數據庫中手工加鎖,而後再經過操做系統的命令來複制相關文件執行熱物理備份,且在完成文件 copy 以前,不能退出加鎖的 session(由於退出會自動解鎖),以下:

    root@localhost :    test    08:36:35>    FLUSH    TABLES    WITH    READ    LOCK;

    Query    OK,    0    rows    affected    (0.00    sec)

不退出 mysql,在新的終端下作以下備份:

mysql@sky:/data/mysql/mydata$ cp    -R    test    /tmp/backup/test mysql@sky:/data/mysql/mydata$ ls    -l    /tmp/backup/ total    4 drwxr-xr-x    2    mysql    mysql    4096    2008-10-19    21:57    test mysql@sky:/data/mysql/mydata$ ls    -l    /tmp/backup/test total    39268

-rw-r-----    1    mysql    mysql

8658    2008-10-19    21:57    hotcopy_his.frm

-rw-r-----    1    mysql    mysql

36    2008-10-19    21:57    hotcopy_his.MYD

-rw-r-----    1    mysql    mysql

1024    2008-10-19    21:57    hotcopy_his.MYI

-rw-r-----    1    mysql    mysql ...    ...

8586    2008-10-19    21:57    memo_test.frm

-rw-rw----    1    mysql    mysql

8554    2008-10-19    22:01    test_csv.frm

-rw-rw----    1    mysql    mysql

    0    2008-10-19    22:01    test_csv.MYD

-rw-rw----    1    mysql    mysql

1024    2008-10-19    22:01    test_csv.MYI

-rw-r-----    1    mysql    mysql

8638    2008-10-19    21:57    test_myisam.frm

    -rw-r-----    1    mysql    mysql    20999600    2008-10-19    21:57    test_myisam.MYD

    -rw-r-----    1    mysql    mysql    10792960    2008-10-19    21:57    test_myisam.MYI

    -rw-r-----    1    mysql    mysql    8638    2008-10-19    21:57    test_outfile.frm

    -rw-r-----    1    mysql    mysql    2400    2008-10-19    21:57    test_outfile.MYD

    -rw-r-----    1    mysql    mysql    1024    2008-10-19    21:57    test_outfile.MYI

    ...    ...

而後再在以前的執行鎖定命令的 session 中解鎖

    root@localhost :    test    10:00:57>    unlock    tables;

    Query    OK,    0    rows    affected    (0.00    sec)

這樣就完成了一次物理備份,並且你們也從文件列表中看到了,備份中還有 CSV 存儲引擎的表。

Innodb 存儲引擎

Innodb 存儲引擎因爲是事務性存儲引擎,有 redo 日誌和相關的 undo 信息,並且對數據的一致性和完整性的要求也比 MyISAM 要嚴格不少,因此 Innodb 的在線(熱)物理備份要比 MyISAM 複雜不少,通常很難簡單的經過幾個手工命令來完成,大都是經過專門的 Innodb 在線物理備份軟件來完成。

Innodb 存儲引擎的開發者(Innobase 公司)開發了一款名爲 ibbackup 的商業備份軟件 ,專門實現 Innodb 存儲引擎數據的在線物理備份功能。該軟件能夠在 MySQL 在線運行的狀態下,對數據庫中使用 Innodb 存儲引擎的表進行備份,不過僅限於使用 Innodb 存儲引擎的表。

因爲這款軟件並非開源免費的產品,我我的也不多使用,主要也是下載的試用版試用而已,因此這裏就不詳細介紹了,各位讀者朋友能夠經過    Innobase    公司官方網站獲取詳細的使用手冊進行試用

NDB    Cluster 存儲引擎

NDB Cluster 存儲引擎也是一款事務性存儲引擎,和 Innodb 同樣也有 redo 日誌。NDB Cluter 存儲引擎本身提供了備份功能,能夠經過相關的命令實現。固然,停機冷備的方法也是有效的。

在線聯機備份步驟以下:

  1. 鏈接上管理服務器;
  2. 在管理節點上面執行    "START    BACKUP"    命令;
  3. 在管理節點上發出備份指令以後,管理節點會通知全部數據節點開始進行備份,並反饋通知結果。
  4. 管理節點在通知發出備份指令以前會生成一個備份號來惟必定位此次備份所產生的備份集。當各數據節點收到備份指令以後,就會開始進行備份操做。
  5. 當全部數據節點都完成備份以後,管理節點纔會反饋"備份完成"的信息給客戶端 。

因爲 NDB Cluster 的備份,備份指令是從管理節點發起,且並不會等待備份完成就會返回,因此也沒辦法直接經過 "Ctrl + c" 或者其餘方式來中斷備份進程,因此 NDB

Cluster    提供了相應的命令來中斷當前正在進行的備份操做,以下:

  1. 登陸管理節點
  2. 執行    "ABORT    BACKUP    backup_id",命令中的    backup_id    即以前發起備份命令的時候所產生的備份號。
  3. 管理結帶你上會用消息"放棄指示的備份 backup_id"確認放棄請求,注意,則時候其實並無收到數據節點對請求的實際迴應。
  4. 而後管理節點纔會將中斷備份的指令發送到全部數據節點上面,而後當各個數據節點都中斷備份並刪除了當前產生的備份文件以後,纔會返回"備份 backup_id 因*

    **而放棄"。至此,中斷備份操做完成。

經過    NDB    Cluster    存儲引擎本身的備份命令來進行備份以後,會將前面所提到的三種文件存放在參與備份的節點上面,且被存放在三個不一樣的文件中,相似以下:

BACKUP-backup_id.node_id.ctl,內容包含相關的控制信息和元數據的控制文件。每一個節點均會將相同的表定義(對於    Cluster    中的全部表)保存在本身的該文件中。

BACKUP-backup_id-n.node_id.data,數據備份文件,被分紅多個不一樣的片斷來保存,在備份過程當中,不一樣的節點將保存不一樣的備份數據所產生的片斷,每一個節點保存的文件都會有信息指明數據所屬表的部分,且在備份片斷文件最後還包含了最後的校驗信息,以確保備份可以正確恢復。

BACKUP-backup_id.node_id.log,事務日誌備份文件中僅包含已提交事務的相關信息,且僅保存已在備份中保存的表上的事務,各個階段所保存的日誌信息也不同,由於僅僅針對各節點所包含的數據記錄相關的日誌信息。

上面的備份文件命名規則中,backup_id 是指備份號,不一樣的備份集會針對有一個不一樣的備份號,node_id 則是指明該備份文件屬於哪一個數據節點,而在數據文件的備份文件中的 n 則是指明片斷號。

5.3.4 各存儲引擎經常使用物理備份恢復方法

和以前邏輯備份同樣,光有備份是沒有意義的,還須要可以將備份有效的恢復才行。物理備份和邏輯備份相比最大的優點就是恢復速度快,由於主要是物理文件的拷貝,將備份文件拷貝到須要恢復的位置,而後進行簡單的才作便可。

MyISAM    存儲引擎

    MyISAM    存儲引擎因爲其特性,物理備份的恢復也比較簡單。

若是是經過停機冷備份或者是在運行狀態經過鎖定寫入操做後的備份集來恢復,僅僅只須要將該備份集直接經過操做系統的拷貝命令將相應的數據文件複製到對應位置來覆蓋現有文件便可。

若是是經過    mysqlhotcopy    軟件來進行的在線熱備份,並且相關的備份信息也記錄進入了數據庫中相應的表,其恢復操做可能會須要結合備份表信息來進行恢復。

Innodb    存儲引擎

對於冷備份,Innodb    存儲引擎進行恢復所須要的操做和其餘存儲引擎沒有什麼差異,一樣是備份集文件(包括數據文件和日誌文件)複製到相應的目錄便可。可是對於經過其餘備份軟件所進行的備份,就須要根據備份軟件自己的要求來進行了。好比經過    ibbackup    來進行的備份,一樣也須要經過他來進行恢復才能夠,具體的恢復方法請經過該軟件的使用手冊來進行,這裏就不詳細介紹了。

NDB    Cluster    存儲引擎

對於停機冷備,恢復方法和其餘存儲引擎也沒有太多區別,只不過有一點須要特別注意的就是恢復的時候必需要將備份集中文件恢復到對應的數據節點之少,不然沒法正確完成恢復過程。

而經過    NDB    Cluster    所提供的備份命令來生成的備份集,須要使用專用的備份恢復軟件    ndb_restore    來進行。ndb_restore    軟件將從備份集中讀取出備份相關的控制信息,並且    ndb_restore    軟件必須在單獨的數據節點上面分別進行。因此當初備份進行過程當中有多少數據節點,如今就須要運行多少次    ndb_restore。並且,首次經過    ndb_restore    來進行恢復的話,還必須恢復元數據,也就是會重建全部的數據庫和表。

5.5 備份策略的設計思路

備份是否完整,可否知足要求,關鍵仍是須要看所設計的備份策略是否合理,以及備份操做是否確實按照所設計的備份策略進行了。

針對於不一樣的用途,所須要的備份類型是不同的,因此須要的備份策略有各有不一樣。如爲了應對本章最開始所描述的在線應用的數據丟失的問題,咱們的備份就須要快速恢復,並且最好是僅僅須要增量恢復就能找回所需數據。對於這類需求,最好是有在線的,且部分延遲恢復的備用數據庫。由於這樣能夠在最短期內找回所須要的數據。甚至在某些硬件設備出現故障的時候,將備用庫直接開發對外提供服務均可以。固然,在資源缺少的狀況下,可能難以找到足夠的備用硬件設備來承擔這個備份責任的時候,咱們也能夠經過物理備份來解決,畢竟物理備份的恢復速度要比邏輯備份的快不少。

而對於那些非數據丟失的應用場景,大多數時候恢復時間的要求並非過高,只要能夠恢復出一個完整可用的數據庫就能夠了。因此不管是物理備份仍是邏輯備份,影響都不大。

從我我的經驗來看,能夠根據不一樣的需求不一樣的級別經過以下的幾個思路來設計出合理的備份策略:

  1. 對於較爲核心的在線應用系統,比須要有在線備用主機經過    MySQL    的複製進行相應的備份,複製線程能夠一直開啓,恢復線程能夠天天恢復一次,儘可能讓備機的數據延後主機在必定的時間段以內。這個延後的時間多長合適主要是根據實際需求決定,通常來講延後一天是一個比較常規的作法。
  2. 對於重要級別稍微低一些的應用,恢復時間要求不是過高的話,爲了節約硬件成本 ,沒必要要使用在線的備份主機來單獨運行備用 MySQL,而是經過每必定的時間週期內進行一次物理全備份,同時每小時(或者其餘合適的時間段)內將產生的二進制日誌進行備份。這樣雖然沒有第一種備份方法恢復快,可是數據的丟失會比較少。恢復所須要的時間由全備週期長短所決定。
  3. 而對於恢復基本沒有太多時間要求,可是不但願太多數據丟失的應用場景,則能夠經過每必定時間週期內進行一次邏輯全備份,同時也備份相應的二進制日誌。使用邏輯備份而不使用物理備份的緣由是由於邏輯備份實現簡單,能夠徹底在線聯機完成,備份過程不會影響應用提供服務。
  4. 對於一些搭建臨時數據庫的備份應用場景,則僅僅只須要經過一個邏輯全備份便可知足需求,都不須要用二進制日誌來進行恢復,由於這樣的需求對數據並無太苛刻的要求。

上面的四種備份策略都還比較較粗糙,甚至不能算是一個備份策略。目的只是但願能給你們一個指定備份策略的思路。各位讀者朋友能夠根據這個思路根據實際的應用場景,指定出各類不一樣的備份策略。

5.6 小結

總的來講,MySQL    的備份與恢復都不是太複雜,方法也比較單一。姑且不說邏輯備份,對於物理備份來講,確實是還不夠完善。缺乏一個開源的比較好的在線熱物理備份軟件,一直是    MySQL    一個比較大的遺憾,也是全部    MySQL    使用者比較鬱悶的事情。

固然,沒有開源的備份軟件使用,非開源的商業軟件也仍是有的,如比較著名的 Zmanda 備份恢復軟件,功能就比較全面,使用也不太複雜,在商業的 MySQL 備份恢復軟件市場上有較高的佔有率。並且,Zmanda 同時還提供社區版本的免費下載使用。

不過,稍微讓人有所安慰的是    MySQL    在實際應用場景中大可能是有一臺或者多臺    Slave 機器來做爲熱備的。在須要進行備份的時候經過    Slave    來進行備份也不是太難,並且經過暫時中止    Slave    上面的    SQL    線程,便可讓    Slave    機器中止全部數據寫入操做,而後就能夠進行在線進行備份操做了。因此即便買不起商用軟件或者不太想買關係也不是太大。

相關文章
相關標籤/搜索