什么樣的備份是數(shù)據(jù)庫邏輯備份呢?
大家都知道,數(shù)據(jù)庫在返回數(shù)據(jù)給我們使用的時候都是按照我們最初所設(shè)計期望的具有一定邏輯關(guān)聯(lián)格式的形式一條一條數(shù)據(jù)來展現(xiàn)的,具有一定的商業(yè)邏輯屬性,而在物理存儲的層面上數(shù)據(jù)庫軟件卻是按照數(shù)據(jù)庫軟件所設(shè)計的某種特定格式經(jīng)過一定的處理后存放。
數(shù)據(jù)庫邏輯備份就是備份軟件按照我們最初所設(shè)計的邏輯關(guān)系,以數(shù)據(jù)庫的邏輯結(jié)構(gòu)對象為單位,將數(shù)據(jù)庫中的數(shù)據(jù)按照預定義的邏輯關(guān)聯(lián)格式一條一條生成相關(guān)的文本文件, 以達到備份的目的。
常用的邏輯備份
邏輯備份可以說是最簡單,也是目前中小型系統(tǒng)最常使用的備份方式。在 MySQL中我們常用的邏輯備份主要就是兩種,一種是將數(shù)據(jù)生成可以完全重現(xiàn)當前數(shù)據(jù)庫中數(shù)據(jù)的INSERT 語句,另外一種就是將數(shù)據(jù)通過邏輯備份軟件,將我們數(shù)據(jù)庫表數(shù)據(jù)以特定分隔符進行分隔后記錄在文本文件中。
1、生成 INSERT 語句備份
兩種邏輯備份各有優(yōu)劣,所針對的使用場景也會稍有差別,我們先來看一下生成 INSERT語句的邏輯備份。
在 MySQL 數(shù)據(jù)庫中,我們一般都是通過 MySQL 數(shù)據(jù)庫軟件自帶工具程序中的 mysqldump來實現(xiàn)聲稱 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”而獲得。這里我只想結(jié)合 MySQL 數(shù)據(jù)庫的一些概念原理和大家探討一下當我們使用mysqldump 來做數(shù)據(jù)庫邏輯備份的時候有些什么技巧以及需要注意一些什么內(nèi)容。
我們都知道,對于大多數(shù)使用數(shù)據(jù)庫的軟件或者網(wǎng)站來說,都希望自己數(shù)據(jù)庫能夠提供盡可能高的可用性,而不是時不時的就需要停機停止提供服務。因為一旦數(shù)據(jù)庫無法提供服務,系統(tǒng)就無法再通過存取數(shù)據(jù)來提供一些動態(tài)功能。所以對于大多數(shù)系統(tǒng)來說如果要讓每次備份都停機來做可能都是不可接受的,可是 mysqldump 程序的實現(xiàn)原理是通過我們給的參數(shù)信息加上數(shù)據(jù)庫中的系統(tǒng)表信息來一個表一個表獲取數(shù)據(jù)然后生成 INSERT 語句再寫入備份文件中的。這樣就出現(xiàn)了一個問題,在系統(tǒng)正常運行過程中,很可能會不斷有數(shù)據(jù)變更的請求正在執(zhí)行, 這樣就可能造成在 mysqldump 備份出來的數(shù)據(jù)不一致。也就是說備份數(shù)據(jù)很可能不是同一個時間點的數(shù)據(jù),而且甚至可能都沒辦法滿足完整性約束。這樣的備份集對于有些系統(tǒng)來說可能并沒有太大問題,但是對于有些對數(shù)據(jù)的一致性和完整性要求比較嚴格系統(tǒng)來說問題就大了,就是一個完全無效的備份集。
對于如此場景,我們該如何做?我們知道,想數(shù)據(jù)庫中的數(shù)據(jù)一致,那么只有兩種情況下可以做到。
第一、同一時刻取出所有數(shù)據(jù);
第二、數(shù)據(jù)庫中的數(shù)據(jù)處于靜止狀態(tài)。
對于第一種情況,大家肯定會想,這可能嗎?不管如何,只要有兩個以上的表,就算我們?nèi)绾螌懗绦颍疾豢赡茏蛲硗耆恢碌娜?shù)時間點啊。是的,我們確實無法通過常規(guī)方法讓取數(shù)的時間點完全一致,但是大家不要忘記,在同一個事務中,數(shù)據(jù)庫是可以做到所讀取的數(shù)據(jù)是處于同一個時間點的。所以,對于事務支持的存儲引擎,如 Innodb 或者 BDB 等 ,我們就可以通過控制將整個備份過程控制在同一個事務中,來達到備份數(shù)據(jù)的一致性和完整性,而且 mysqldump 程序也給我們提供了相關(guān)的參數(shù)選項來支持該功能,就是通過 “–single-transaction”選項,可以不影響數(shù)據(jù)庫的任何正常服務。
對于第二種情況我想大家首先想到的肯定是將需要備份的表鎖定,只允許讀取而不允許寫入。是的,我們確實只能這么做。我們只能通過一個折衷的處理方式,讓數(shù)據(jù)庫在備份過程中僅提供數(shù)據(jù)的查詢服務,鎖定寫入的服務,來使數(shù)據(jù)暫時處于一個一致的不會被修改的狀態(tài),等 mysqldump 完成備份后再取消寫入鎖定,重新開始提供完整的服務。mysqldump 程序自己也提供了相關(guān)選項如“–lock-tables”和“–lock-all-tables”,在執(zhí)行之前會鎖定表,執(zhí)行結(jié)束后自動釋放鎖定。這里有一點需要注意的就是, “–lock-tables”并不是一次性將需要 dump 的所有表鎖定,而是每次僅僅鎖定一個數(shù)據(jù)庫的表,如果你需要 dump 的表分別在多個不同的數(shù)據(jù)庫中,一定要使用“–lock-all-tables”才能確保數(shù)據(jù)的一致完整性。
當通過 mysqldump 生成 INSERT 語句的邏輯備份文件的時候,有一個非常有用的選項可以供我們使用,那就是 “–master-data[=value]”。當添加了 “–master-data=1”的時候,mysqldump 會將當前 MySQL 使用到 binlog 日志的名稱和位置記錄到 dump 文件中,并且是被以 CHANGE_MASTER 語句的形式記錄,如果僅僅只是使用“–master-data”或者“–masterdata=2”,則 CHANGE_MASTER 語句會以注釋的形式存在。這個選項在實施 slave 的在線搭建的時候是非常有用的,即使不是進行在線搭建 slave,也可以在某些情況下做恢復的過程中通過備份的 binlog 做進一步恢復操作。
在某些場景下,我們可能只是為了將某些特殊的數(shù)據(jù)導出到其他數(shù)據(jù)庫中,而又不希望通過先建臨時表的方式來實現(xiàn),我們還可以在通過 mysqldump 程序的“—where=’wherecondition’”來實現(xiàn),但只能在僅 dump 一個表的情況下使用。其實除了以上一些使用訣竅之外, mysqldump 還提供了其他很多有用的選項供大家在不同的場景下只用,如通過 “–no-data”僅僅 dump 數(shù)據(jù)庫結(jié)構(gòu)創(chuàng)建腳本,通過 “–no-createinfo”去掉 dump 文件中創(chuàng)建表結(jié)構(gòu)的命令等等,感興趣的讀者朋友可以詳細閱讀 mysqldump程序的使用介紹再自行測試。
2、生成特定格式的純文本備份數(shù)據(jù)文件備份
除了通過生成 INSERT 命令來做邏輯備份之外,我們還可以通過另外一種方式將數(shù)據(jù)庫中的數(shù)據(jù)以特定分隔字符將數(shù)據(jù)分隔記錄在文本文件中,以達到邏輯備份的效果。這樣的備份數(shù)據(jù)與 INSERT 命令文件相比,所需要使用的存儲空間更小,數(shù)據(jù)格式更加清晰明確,編輯方便。但是缺點是在同一個備份文件中不能存在多個表的備份數(shù)據(jù),沒有數(shù)據(jù)庫結(jié)構(gòu)的重建命令。對于備份集需要多個文件,對我們產(chǎn)生的影響無非就是文件多了維護和恢復成本增加,但這些基本上都可以通過編寫一些簡單的腳本來實現(xiàn)
那我們一般可以使用什么方法來生成這樣的備份集文件呢,其實 MySQL 也已經(jīng)給我們實現(xiàn)的相應的功能。
在 MySQL 中一般都使用以下兩種方法來獲得可以自定義分隔符的純文本備份文件。
1、通過執(zhí)行 SELECT … TO OUTFILE FROM …命令來實現(xiàn)
在 MySQL 中提供了一種 SELECT 語法,專供用戶通過 SQL 語句將某些特定數(shù)據(jù)以指定格式輸出到文本文件中,同時也提供了實用工具和相關(guān)的命令可以方便的將導出文件原樣再導入到數(shù)據(jù)庫中。正不正是我們做備份所需要的么?
該命令有幾個需要注意的參數(shù)如下:
實現(xiàn)字符轉(zhuǎn)義功能的“FIELDS ESCAPED BY [‘name’]” 將 SQL 語句中需要轉(zhuǎn)義的字符進行轉(zhuǎn)義;
可以將字段的內(nèi)容“包裝”起來的“FIELDS [OPTIONALLY] ENCLOSED BY ‘name’”,如果不使用 “OPTIONALLY”則包括數(shù)字類型的所有類型數(shù)據(jù)都會被 “包裝”,使 用 “OPTIONALLY”之后,則數(shù)字類型的數(shù)據(jù)不會被指定字符“包裝”。
通過”FIELDS TERMINATED BY”可以設(shè)定每兩個字段之間的分隔符;
而通過“LINES TERMINATED BY”則會告訴 MySQL 輸出文件在每條記錄結(jié)束的時候需要
添加什么字符。
如以下示例:
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”
… …
2、通過 mysqldump 導出
可能我們都知道 mysqldump 可以將數(shù)據(jù)庫中的數(shù)據(jù)以 INSERT 語句的形式生成相關(guān)備份文件,其實除了生成 INSERT 語句之外,mysqldump 還同樣能實現(xiàn)上面“SELECT … TOOUTFILE FROM …”所實現(xiàn)的功能,而且同時還會生成一個相關(guān)數(shù)據(jù)庫結(jié)構(gòu)對應的創(chuàng)建腳本 。
如以下示例:
root@sky:~# ls -l /tmp/mysqldump
total 0
root@sky:~# mysqldump -uroot -T/tmp/mysqldump test test_outfile –fieldsenclosed-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
這樣的輸出結(jié)構(gòu)對我們做為備份來使用是非常合適的,當然如果一次有多個表需要被dump,就會針對每個表都會生成兩個相對應的文件。
?以上就是Mysql數(shù)據(jù)備份之邏輯備份的內(nèi)容,更多相關(guān)內(nèi)容請關(guān)注PHP中文網(wǎng)(www.php.cn)!