前言 node
數據庫的備份與恢復一直都是 DBA 工做中最爲重要的部分之一,也是基本工做之一。任何正式環境的數據庫都必須有完整的備份計劃和恢復測試,本章內容將主要介紹 MySQL 數據庫的備份與恢復相關內容。 mysql
你真的明白了本身所作的數據庫備份是要面對什麼樣的場景的嗎? 正則表達式
我想任何一位維護過數據庫的人都知道數據庫是須要備份的,也知道備份數據庫是數據庫維護必不可少的一件事情。那麼是否每個人都知道本身所作的備份究竟是爲了應對哪些場景的呢?抑或者說咱們每一個人是否都很清楚的知道,爲何一個數據庫須要做備份呢?讀到這裏,我想不少讀者朋友都會嗤之以鼻,"備份的做用不就是爲了防止原數據丟失嗎,這誰不知道?"。確實,數據庫的備份很大程度上的做用,就是當咱們的數據庫由於某些緣由而形成部分或者所有數據丟失後,方便找回丟失的數據。可是,不一樣類型的數據庫備份,所能應付狀況是不同的,並且,數據庫的備份同時也還具備其餘不少的做用。並且我想,每一個人對數據庫備份的做用的理解可能都會有部分區別。 sql
下面我就列舉一下我我的理解的咱們可以須要用到數據庫備份的一些比較常見的狀況吧。 數據庫
1、數據丟失應用場景 安全
一、人爲操做失誤形成某些數據被誤操做; 二、軟件 BUG 形成數據部分或者所有丟失; 服務器
2、非數據丟失應用場景 session
上面所列出的只是一些常見的應用場景而已,除了上面這幾種場景外,數據庫備份還會有不少其餘應用場景,這裏就不一一列舉了。那麼各位讀者過曾經或是如今所作的數據庫備份究竟是爲了應對以上哪種(或者幾種)場景?或者說,咱們所作的數據庫備份可以應對以上哪幾種應用場景?不知道這個問題你們是否有考慮過。 工具
咱們必須認可,沒有哪種數據庫備份可以解決全部以上列舉的幾種常見應用場景,即便僅僅只是數據丟失的各類場景都沒法經過某一種數據庫備份完美的解決,固然也就更不用說可以解決全部的備份應用場景了。 測試
好比當咱們遇到磁盤故障,丟失了整個數據庫的全部數據,而且沒法從已經出現故障的硬盤上面恢復出來的時候,咱們可能必須經過一個實時或者有短暫時間差的複製備份數據庫存在。固然若是沒有這樣的一個數據庫,就必需要有最近時間的整個數據庫的物理或者邏輯備份數據,而且有該備份以後的全部物理或者邏輯增量備份,以指望儘量將數據恢復到出現故障以前最近的時間點。而當咱們遇到認爲操做失誤形成數據被誤操做以後,咱們須要有一個能恢復到錯誤操做時間點以前的瞬間的備份存在,固然這個備份多是整個數據庫的備份,也能夠僅僅只是被誤操做的表的備份。而當咱們要作跨平臺的數據庫遷移的時候,咱們所須要的又只能是一個邏輯的數據庫備份,由於平臺的差別可能使物理備份的文件格式在兩個平臺上沒法兼容。
既然沒有哪種不少中數據庫備份可以完美的解決全部的應用場景,而每一個數據庫環境所須要面對的數據庫備份應用場景又可能各不同,可能只是須要面對不少種場景中的某一種或幾種,那麼咱們就很是有必要指定一個合適的備份方案和備份策略,經過最簡單的技術和最低廉的成本,來知足咱們的需求。
你們都知道,數據庫在返回數據給咱們使用的時候都是按照咱們最初所設計指望的具備必定邏輯關聯格式的形式一條一條數據來展示的,具備必定的商業邏輯屬性,而在物理存儲的層面上數據庫軟件倒是按照數據庫軟件所設計的某種特定格式通過必定的處理後存放。
數據庫邏輯備份就是備份軟件按照咱們最初所設計的邏輯關係,以數據庫的邏輯結構對象爲單位,將數據庫中的數據按照預約義的邏輯關聯格式一條一條生成相關的文本文件,以達到備份的目的。
邏輯備份能夠說是最簡單,也是目前中小型系統最常使用的備份方式。在 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,就會針對每一個表都會生成兩個相對應的文件。
僅僅有了備份仍是不夠啊,咱們得知道如何去使用這些備份,如今咱們就看看上面所作的邏輯備份的恢復方法:
因爲全部的備份數據都是以咱們最初數據庫結構的設計相關的形式所存儲,因此邏輯備份的恢復也相對比較簡單。固然,針對兩種不一樣的邏輯備份形式,恢復方法也稍有區別。下面咱們就分別針對這兩種邏輯備份文件的恢復方法作一個簡單的介紹。
對於 INSERT 語句形式的備份文件的恢復是最簡單的,咱們僅僅只須要運行該備份文件中的全部(或者部分)SQL 命令便可。首先,若是須要作徹底恢復,那麼咱們能夠經過使用 "mysql < backup.sql"直接調用備份文件執行其中的全部命令,將數據徹底恢復到備份時候的狀態。若是已經使用 mysql 鏈接上了 MySQL,那麼也能夠經過在 mysql 中執行"source
/path/backup.sql"或者"\. /path/backup.sql"來進行恢復。
若是是上面第二中形式的邏輯備份,恢復起來會稍微麻煩一點,須要一個表一個表經過相關命令來進行恢復,固然若是經過腳原本實現自動多表恢復也是比較方便的。恢復方法也有兩個,一是經過 MySQL 的"LOAD DATA INFILE"命令來實現,另外一種方法就是經過 MySQL 提供的使用工具 mysqlimport 來進行恢復。
邏輯備份能作什麼?不能作什麼?
在清楚瞭如何使用邏輯備份進行相應的恢復以後,咱們須要知道咱們能夠利用這些邏輯備份作些什麼。
在知道了邏輯備份能作什麼以後,咱們必須還要清楚他不能作什麼,這樣咱們本身才能清楚的知道這樣的一個備份可否知足本身的預期,是否確實是本身想要的。
5.2.4 邏輯備份恢復測試
時有聽到某某的數據庫出現問題,而當其信心十足的準備拿以前所作好的數據庫進行恢復的時候才發現本身的備份集不可用,或者並不能達到本身作備份時候所預期的恢復效果。遇到這種情景的時候,恐怕每一個人都會鬱悶至極的。數據庫備份最重要最關鍵的一個用途就是當咱們的數據庫出現某些異常情況,須要對數據進行恢復的時候使用的。做爲一個維護人員,咱們是絕對不該該出現此類低級錯誤的。那咱們到底該如何避免此類問題呢?只有一個辦法,那就是週期性的進行模擬恢復測試,校驗咱們的備份集是否真的有效,是否確實可以按照咱們的備份預期進行相應的恢復。
到這裏可能有人會問,恢復測試又該如何作呢,咱們總不能真的將線上環境的數據進行恢復啊?是的,線上環境的數據確實不能被恢復,可是咱們爲何不能在測試環境或者其餘的地方作呢?作恢復測試只是爲了驗證咱們的備份是否有效,是否能達到咱們的預期。因此在作恢復測試以前咱們必定要先清楚的知道咱們所作的備份究竟是爲了應用於什麼樣的場景的。就好比咱們作了一個全庫的邏輯備份,目的多是爲了當數據庫出現邏輯或者物理異常的時候可以恢復整個數據庫的數據到備份時刻,那麼咱們惡的恢復測試就只須要將整個邏輯備份進行全庫恢復,看是否可以成功的重建一個完整的數據庫。至於恢復的數據是否和備份時刻一致,就只能依靠咱們本身來人工判斷比較。此外咱們可能還但願當某一個數據庫對象,好比某個表出現問題以後可以儘快的恢復該表數據到備份時刻。那麼咱們就能夠針對單個指定表進行抽樣恢復測試。
下面咱們就假想數據庫主機崩潰,硬件損壞,形成數據庫數據所有丟失,來作一次全庫恢復的測試示例:
當咱們的數據庫出現硬件故障,數據所有丟失以後,咱們必須儘快找到一臺新的主機以頂替損壞的主機來恢復相應的服務。在恢復服務以前,咱們首先須要重建損壞的數據庫。假設咱們已經拿到了一臺新的主機,MySQL 軟件也已經安裝就位,相關設置也都已經調整好,就等着恢復數據庫了。
咱們須要取回離崩潰時間最近的一次全庫邏輯備份文件,複製到準備的新主機上,啓動已經安裝好的 MySQL。
因爲咱們有兩種邏輯備份格式,每種格式的恢復方法並不同,因此這裏將對兩種格式的邏輯備份的恢復都進行示例。
一、若是是 INSERT 語句的邏輯備份
或者先經過 mysql 登陸到數據庫中,而後再執行以下命令:
root@localhost : (none) 09:59:40> source /tmp/backup.sql
固然上面所說的步驟都是在默認每一步都正常的前提下進行的,若是發現某一步有問題。倘若在 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 語句備份的恢復徹底同樣了,這裏就再也不累述。
前面一節咱們瞭解瞭如何使用 MySQL 的邏輯備份,並作了一個簡單的邏輯備份恢復示例,在這一節咱們再一塊兒瞭解一些 MySQL 的物理備份。
在瞭解 MySQL 的物理備份以前,咱們須要先了解一下,什麼是數據庫物理備份?既然是物理備份,那麼確定是和數據庫的物理對象相對應的。就如同邏輯備份根據由咱們根據業務邏輯所設計的數據庫邏輯對象所作的備份同樣,數據庫的物理備份就是對數據庫的物理對象所作的備份。數據庫的物理對象主要由數據庫的物理數據文件、日誌文件以及配置文件等組成。在 MySQL 數據庫中,除了 MySQL 系統共有的一些日誌文件和系統表的數據文件以外,每一種存儲引擎本身還會有不太同樣的物理對象,在以前第一篇的"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)的物理備份須要備份的文件主要有一下三類:
不管是經過停機冷備份,仍是經過 NDB Cluster 自行提供的在線聯機備份工具,或者是第三方備份軟件來進行備份,都須要備份以上三種物理文件才能構成一個完整有效的備份集。固然,相關的配置文件,尤爲是管理節點上面的配置信息,一樣也須要備份。
因爲不一樣存儲引擎所須要備份的物理對象(文件)並不同,且每一個存儲引擎對數據文件的一致性要求也不同因此各個存儲引擎在進行物理備份的時候所使用的備份方法也有區別。固然,若是咱們是要作冷備份(停掉數據庫以後的備份),咱們所須要作的事情都很簡單,那就是直接 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 存儲引擎本身提供了備份功能,能夠經過相關的命令實現。固然,停機冷備的方法也是有效的。
在線聯機備份步驟以下:
因爲 NDB Cluster 的備份,備份指令是從管理節點發起,且並不會等待備份完成就會返回,因此也沒辦法直接經過 "Ctrl + c" 或者其餘方式來中斷備份進程,因此 NDB
Cluster 提供了相應的命令來中斷當前正在進行的備份操做,以下:
**而放棄"。至此,中斷備份操做完成。
經過 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 則是指明片斷號。
和以前邏輯備份同樣,光有備份是沒有意義的,還須要可以將備份有效的恢復才行。物理備份和邏輯備份相比最大的優點就是恢復速度快,由於主要是物理文件的拷貝,將備份文件拷貝到須要恢復的位置,而後進行簡單的才作便可。
MyISAM 存儲引擎
MyISAM 存儲引擎因爲其特性,物理備份的恢復也比較簡單。
若是是經過停機冷備份或者是在運行狀態經過鎖定寫入操做後的備份集來恢復,僅僅只須要將該備份集直接經過操做系統的拷貝命令將相應的數據文件複製到對應位置來覆蓋現有文件便可。
若是是經過 mysqlhotcopy 軟件來進行的在線熱備份,並且相關的備份信息也記錄進入了數據庫中相應的表,其恢復操做可能會須要結合備份表信息來進行恢復。
Innodb 存儲引擎
對於冷備份,Innodb 存儲引擎進行恢復所須要的操做和其餘存儲引擎沒有什麼差異,一樣是備份集文件(包括數據文件和日誌文件)複製到相應的目錄便可。可是對於經過其餘備份軟件所進行的備份,就須要根據備份軟件自己的要求來進行了。好比經過 ibbackup 來進行的備份,一樣也須要經過他來進行恢復才能夠,具體的恢復方法請經過該軟件的使用手冊來進行,這裏就不詳細介紹了。
NDB Cluster 存儲引擎
對於停機冷備,恢復方法和其餘存儲引擎也沒有太多區別,只不過有一點須要特別注意的就是恢復的時候必需要將備份集中文件恢復到對應的數據節點之少,不然沒法正確完成恢復過程。
而經過 NDB Cluster 所提供的備份命令來生成的備份集,須要使用專用的備份恢復軟件 ndb_restore 來進行。ndb_restore 軟件將從備份集中讀取出備份相關的控制信息,並且 ndb_restore 軟件必須在單獨的數據節點上面分別進行。因此當初備份進行過程當中有多少數據節點,如今就須要運行多少次 ndb_restore。並且,首次經過 ndb_restore 來進行恢復的話,還必須恢復元數據,也就是會重建全部的數據庫和表。
備份是否完整,可否知足要求,關鍵仍是須要看所設計的備份策略是否合理,以及備份操做是否確實按照所設計的備份策略進行了。
針對於不一樣的用途,所須要的備份類型是不同的,因此須要的備份策略有各有不一樣。如爲了應對本章最開始所描述的在線應用的數據丟失的問題,咱們的備份就須要快速恢復,並且最好是僅僅須要增量恢復就能找回所需數據。對於這類需求,最好是有在線的,且部分延遲恢復的備用數據庫。由於這樣能夠在最短期內找回所須要的數據。甚至在某些硬件設備出現故障的時候,將備用庫直接開發對外提供服務均可以。固然,在資源缺少的狀況下,可能難以找到足夠的備用硬件設備來承擔這個備份責任的時候,咱們也能夠經過物理備份來解決,畢竟物理備份的恢復速度要比邏輯備份的快不少。
而對於那些非數據丟失的應用場景,大多數時候恢復時間的要求並非過高,只要能夠恢復出一個完整可用的數據庫就能夠了。因此不管是物理備份仍是邏輯備份,影響都不大。
從我我的經驗來看,能夠根據不一樣的需求不一樣的級別經過以下的幾個思路來設計出合理的備份策略:
上面的四種備份策略都還比較較粗糙,甚至不能算是一個備份策略。目的只是但願能給你們一個指定備份策略的思路。各位讀者朋友能夠根據這個思路根據實際的應用場景,指定出各類不一樣的備份策略。
總的來講,MySQL 的備份與恢復都不是太複雜,方法也比較單一。姑且不說邏輯備份,對於物理備份來講,確實是還不夠完善。缺乏一個開源的比較好的在線熱物理備份軟件,一直是 MySQL 一個比較大的遺憾,也是全部 MySQL 使用者比較鬱悶的事情。
固然,沒有開源的備份軟件使用,非開源的商業軟件也仍是有的,如比較著名的 Zmanda 備份恢復軟件,功能就比較全面,使用也不太複雜,在商業的 MySQL 備份恢復軟件市場上有較高的佔有率。並且,Zmanda 同時還提供社區版本的免費下載使用。
不過,稍微讓人有所安慰的是 MySQL 在實際應用場景中大可能是有一臺或者多臺 Slave 機器來做爲熱備的。在須要進行備份的時候經過 Slave 來進行備份也不是太難,並且經過暫時中止 Slave 上面的 SQL 線程,便可讓 Slave 機器中止全部數據寫入操做,而後就能夠進行在線進行備份操做了。因此即便買不起商用軟件或者不太想買關係也不是太大。