Mysql備份與恢復


目錄

備份的分類

    物理備份與邏輯備份

    熱備份與冷備份

    完全備份與增量備份

    更多內容

完全備份與恢復

    以SQL語句格式導入導出數據庫

          以SQL語句格式導出數據

          導入SQL語句形式的文件

    以分隔符格式導入導出數據庫

          以分隔符格式導出數據庫

          導入分隔符格式的文件

    mysqldump技巧

           復制一個數據庫的內容到另一個數據庫

           復制一個數據庫到另一台主機上

           導出已經存儲的程序

           分開導出數據庫表的定義和數據內容

           使用mysqldump來測試升級數據庫的兼容性

增量備份與時間點恢復

     操作日志文件

     使用時間點來恢復數據

     使用事件點來恢復數據

 

備份的分類

物理備份與邏輯備份

物理備份是由原始的數據庫文件組成,這種類型的備份適用於大型且重要的數據庫,因為可以在數據庫發生問題時快速恢復。

邏輯備份是由數據庫的邏輯語句組成(如CREATE DATABASE,CREATE TABLE,INSERT等語句)。這種類型的備份適用於少量的數據,尤其是在你可能會改變表結構的情況下。

物理備份有以下特征:

1. 備份文件是由數據庫的目錄和文件組成,完全就是mysql數據目錄的一個復制副本

2. 物理備份比邏輯備份快是因為物理備份單純地復制文件,而沒有進行邏輯轉換

3. 輸出更加簡潔,緊湊

4. 因為備份速度和簡潔性對於重要,繁忙的數據庫來說非常重要,所以mysql的企業版使用物理備份

5. 備份的文件只適用於同一種架構的計算機

6. 根據數據庫引擎來決定備份的粒度但一般不能細分到備份某個表,InnoDB可以細分到一個獨立的文件

7. 除了備份數據庫,還可以備份相關的文件如日志和配置文件

8. 在mysql服務器停止運行期間可以執行物理備份,但在服務器運行期間需要先鎖定服務器,為了防止在備份期間寫入數據

9. 備份工具包括mysqlbackup(mysql企業版專有),文件復制命令(cp, scp, tar, rsync)或者mysqlhotcopy(只適用於MyISAM表)

邏輯備份有如下特征:

1. 通過查詢mysql服務器,獲得數據庫結構和內容,來完成邏輯備份

2. 邏輯備份比物理備份速度慢是因為服務器要訪問並轉換數據庫信息為邏輯語句形式

3. 備份后的文件比邏輯備份文件大

4. 備份粒度包括服務器級別(所有的數據庫),數據庫級別(某個數據庫所有的表)或者某個表

5. 備份不包括與數據庫無關的文件,如日志和配置文件

6. 備份文件適用於所有的計算機架構

7. 只能在mysql服務器運行的時候進行邏輯備份

8. 邏輯備份的工具包括mysqldump和select … into outfile語句

熱備份與冷備份

熱(hot)備份指的是在運行mysql服務器的過程中備份,冷(cold)備份指的是在停止mysql服務器后備份,而暖(warm)備份是指在備份的手給正在運行的mysql服務器加鎖,防止數據庫文件改變

熱備份的特征:

1. 不會嚴重干擾(intrusive)到其他客戶端,因為在執行備份時,其他客戶端可能會訪問到數據庫

2. 一定要記得給服務器加鎖,否則在備份期間改變了數據庫會影響到備份的完整性,mysql企業版會在備份時自動加鎖

 

冷備份的特征:

1. 在備份期間,客戶端不能訪問到數據庫,所以,通過會在從服務器(這里指的是配置了主從同步的從服務器)上進行備份

2. 備份程序比較簡單

 

完全備份與增量備份

完全備份備份了某個時間點的mysql服務器的全部數據,而增量備份備份了在一個指定的時間點之后有變動的數據。增量備份是通過       mysql服務器的binary log(二進制日志,該日志記錄了數據的變動情況)來執行的

 

備份調度是用來自動執行備份程序的,壓縮備份文件可以減小備份文件的大小,加密備份可以提供更高的安全性。但是mysql本身並不提供這些功能,可以mysql企業版或者第三方的解決方案。

 

完全備份與恢復

這一部分的內容用來描述如何使用mysqldump命令來產生導出文件,和如何導入這些導出文件。

下面這張圖顯示了下面范例所用的數據庫和數據庫的內容

圖片1

 

mysqldump根據--tab選項來產生兩種類型的輸出文件:

1. 沒有--tab選項,mysqldump命令把標准的SQL語句寫入到輸出文件中,該文件包括CREATE語句來創建導出對象(數據庫,表等),  INSERT語句來往表中寫入數據,這個文件可以使用mysql命令來重新創建導出的對象,可以通過選項來控制SQL語句格式和某個導出的對象。(參考下面的“以SQL語句格式導入導出數據庫”)

圖片2

上圖就是以SQL格式導出的文件

 

2. 使用--tab命令,mysqldump會為數據庫中的每一個表產生兩個輸出文件,mysql服務器會以tab作為分隔符來寫入一個文件(該文件名為tbl_name.txt),同時服務器會創建一個名為tbl_name.sql文件,該文件只包含建表語句(CREATE TABLE)(參考下面的“以分隔符格式導入導出數據庫”)

圖片3

上圖就是以分隔符形式導出的文件

 

以SQL語句格式導出數據

默認地,mysqldump以SQL語句的方式寫入到標准輸出文件中,典型的用法如下(記得先開啟mysql數據庫):

shell > mysqldump [arguments] > file_name

注意:真正在shell中使用mysqldump命令時,需要顯式地加上mysql連接信息,下面的所有命令為了簡潔而省略了這些信息。

可以在shell終端中直接輸入命令,就得到mysqldump的使用幫助(附件一)

[root@localhost ~]# mysqldump --help

下面舉出幾個常用的命令:

為了導出所有數據庫,需要用--all-databases選項

shell > mysqldump --all-databases > dump.sql

示范命令:在shell中真正使用這條語句時是下面這樣的(以日期的格式命名,

-uroot指的是以root的身份登錄,-p'123456'指的是密碼,注意不能有空格,后面的命令就不再一一示范了):

[root@localhost ~]# mysqldump --all-databases -uroot -p'123456' > /server/backup/bak_$(date +%F).sql

為了導出指定的數據庫(一個或多個數據庫),需要用--databases選項(或者-B)

shell > mysqldump --databases db1 db2 db3 > dump.sql

而導出指定數據庫的哪一張表,則忽略掉--databases選項(db1數據庫中的table1和table2)

shell > mysqldump db1 table1 table2> dump.sql

在導出單個指定的數據庫時,除了像上面一樣使用--databases以外,還可以這樣:

shell > mysqldump db1 > dump.sql

但是,忽略了--databases選項后,需要注意這點:

輸出文件中沒有CREATE DATABASE和USE語句,所以當你重新導入這個導出文件時,你必須指定一個默認的數據庫(或者自己創建一個數據庫);與此同時,你也可以把這個導出文件導入到另一個數據庫上

導入SQL語句形式的文件

當使用上面的mysqldump語句導出文件的時候使用到了--all-databases或者

--databases選項后,文件中已經含有了CREATE DATABASE和USE語句,所以不需要再指定一個數據庫,可以直接讀入該文件

shell > mysql < dump.sql

示范語句:

[root@localhost ~]# mysql -uroot -p'123456' </server/backup/dump.sql

或者,先登錄mysql,在mysql中進行導入

mysql > source /server/backup/dump.sql;

但是,如果導出文件中不包含CREATE DATABASE和USE語句,此時就要手動創建數據,再讀入該文件。

shell > mysqladmin create db1

示范語句:

[root@localhost backup]# mysqladmin -uroot -p'123456' create db_test;

然后在導入文件時指定數據庫名字:

shell > mysql db1 < dump.sql;

或者先登錄mysql,然后導入文件

mysql > create database if not exists db1;

mysql > use db1;

mysql > source dump.sql;

 

以分隔符格式導出數據庫

在使用mysqldump命令時,如果加上了--tab=dir_name選項,就會在dir_name目錄為數據庫中的每個表生成兩個文件,以txt為后綴的文件用來存儲數據,以sql為后綴的文件用來存儲CREATE TABLE的建表語句,下面的語句用來導出db1數據庫的內容到/tmp目錄下

shell > mysqldump --tab=/tmp db1

示范語句:

[root@localhost backup]# mysqldump -uroot -p'123456' --tab=/server/backup/tmp/ kylin_default

注意:如果看到了下面所示的錯誤

mysqldump: Got error: 1: Can't create/write to file '/server/backup/tmp/course.txt' (Errcode: 13 - Permission denied) when executing 'SELECT INTO OUTFILE'

是因為/server/backup/tmp目錄的權限問題,導致mysql不能寫入到該目錄下,解決方法就是授權該目錄

[root@localhost backup]# chmod a+rwx tmp/

當使用--tab選項時,最好只導出本地的mysql服務器的數據庫,如果要導出遠程的數據庫,那么導出的目錄必須同時存在於兩個服務器中,並且txt文件會寫入到遠程的服務器的目錄中,而sql文件會寫入到本地服務器目錄中

可以通過選項自定義txt文件的導出格式:

  1. --fields-terminated-by=str 在txt文件中用來分隔每一列的內容(默認是tab)
  2. --fields-enclosed-by=char  在txt文件中用來封閉每一個值的內容(例如用雙引號把所有的值括起來,默認為空)
  3. --fields-optionally-enclosed-by=char 在txt文件中用來封閉非數值的內容(默認為空)
  4. --fields-escaped-by=char 忽略特定的字符
  5. --lines-terminated-by=str 每一行的行終止符(默認是換行符)

譬如,導出的文件中,用逗號分隔每一列的值,並且用雙引號括起來,在行末用\r\n(windows環境下的換行符)作為終止符

[root@localhost tmp]# mysqldump -uroot -p'123456' --tab=/server/backup/tmp/ --fields-terminated-by=, --fields-enclosed-by='"' --lines-terminated-by=0x0d0a kylin_default

輸出格式有前面的圖變為下面這個

圖片4

導入分隔符格式的文件

先導入sql后綴的文件,再導入txt文件

shell > mysql db1 < t1.sql

shell > mysqlimport db1 t1.txt

示范語句:

[root@localhost tmp]# mysql -uroot -p'123456' kylin_default < test.sql

[root@localhost tmp]# mysqlimport -uroot -p'123456' kylin_default /server/backup/tmp/test.txt;

或者登陸mysql后操作

mysql > use db1;

mysql > load data infile ‘t1.txt’ into table t1;

注意:如果你導出數據庫時使用了自定義的格式,在導入該文件到數據庫時也必須指定同樣的格式,否則會發生錯誤

如:

shell > mysqlimport --fields-terminated-by=, --fields-enclosed-by='"' --lines-terminated-by=0x0d0a db1 t1.txt

或者

mysql > use db1;

mysql > load data infile ‘t1.txt’ into table t1

> fields terminated by ',' fields enclosed by ' " '

> lines terminated by '\r\b' ;

 

mysqldump技巧

復制一個數據庫的內容到另一個數據庫
shell > mysqldump db1 > dump.sql

shell > mysqladmin create db2

shell > mysql db2 < dump.sql

在使用mysqldump命令時只要不加上--databases選項,就會使得導出的SQL文件中沒有USE db1語句,從而使得該文件可以導入到另一個不同名的數據庫中

 

復制一個數據庫到另一台主機上

在服務器1上執行:

shell > mysqldump --databases db1 > dump.sql

然后把dump.sql文件拷貝到服務器2上,在服務器2上執行:

shell > mysql < dump.sql

在使用mysqldump命令時加上--databases選項,就會使得導出的SQL文件中包含有CREATE DATABASE和USE db1語句,所以可以在沒有db1的服務器上直接導入該文件(因為會自動生成db1)

當然,也可以不使用--databases選項,只要在服務器2上手動創建一個數據庫,然后往該數據庫導入該文件即可

 

導出已經存儲的程序

mysqldump還可以處理存儲的程序(stored programs)(存儲進程,函數,觸發器和事件(events)):

  1. --events:Dump Event Scheduler events
  2. --routines: Dump stored procedures and functions
  3. --triggers: Dump triggers for tables

--triggers選項是默認執行的,而其余兩個選項是要自己手動添加的,如果要明確禁止導出這三個程序,就使用選項:--skip-events, --skip-routines, --skip-triggers

 

分開導出數據庫表的定義和數據內容

使用--no-data選項可以告訴mysqldump只導出數據庫的表定義語句,而不導出數據內容

shell > mysqldump --no-data test > dump-defs.sql

示范語句:

[root@localhost backup]# mysqldump -uroot -p'123456' --no-data kylin_default > /server/backup/no_data.sql

圖片5

可以看到該文件只包含了創建表的語句

使用--no-create-info選項可以告訴mysqldump只導出數據庫的數據操作語句,而不導出數據庫的表定義

shell > mysqldump --no-create-info test > dump-data.sql

示范語句:

[root@localhost backup]# mysqldump -uroot -p'123456' --no-create-info kylin_default > /server/backup/no_create_into.sql

圖片6

可以看到該文件只包含了操作數據(這里僅僅是插入數據)的內容

 

使用mysqldump來測試升級數據庫的兼容性

當打算升級mysql服務器時,應當首先測試新版本數據庫。可以把舊服務器的數據導入到新服務器中,測試新版本的服務器是否能正確處理數據。

在舊的服務器中執行:

shell > mysqldump --all-databases --no-data --routines --events > dump-defs.sql

在新的服務器中執行

shell > mysql < dump-defs.sql

因為導出的文件中沒有數據,所以可以快速執行,你應當留意在執行過程中出現的所有警告和錯誤

在你確認了在新服務器中已經正確生成了數據庫,此時就可以往新服務器中導入數據

在舊的服務器中執行:

shell > mysqldump --all-databases --no-create-info > dump-data.sql

在新的服務器中執行

shell > mysql < dump-data.sql

然后檢查數據內容和運行一些測試程序

 

增量備份與時間點恢復

時間點恢復指的是首先指定一個時間點,然后讓mysql服務器執行該時間點之后的全部操作。通常,時間點恢復會在執行了一個全備份之后才能運行,因為在完成全備份的時候,服務器會記錄當時的狀態和時間(換個角度想,有a,b兩個數據庫,b首先全備份了a的數據庫,然后a的數據庫的內容發生了改變,這時候b數據庫只要執行a數據改變的語句就能保持和a的一致)

操作日志文件

時間點恢復的要點:

時間點恢復需要用到一個二進制的日志文件,該文件是在執行全備份之后生成的,因此,服務器必須先啟用--long-bin配置選項才能生成二進制文件。服務器默認會在數據存儲的目錄存放該日志,當然你可以指定另一個存放目錄

修改你的my.cnf文件,在[mysqd]模塊下增加內容:log-bin=mysql-bin,然后重啟數據庫。然后馬上執行一次全備份,因為日志文件是記錄全備份之后的SQL語句,如果不在每一次導入日志文件前先導入全備份的數據庫,就會造成錯誤(譬如對於一條插入語句,如果直接導入日志文件,就會提示ERROR 1062 (23000) at line XX: Duplicate entry 'X' for key 'PRIMARY',因為這條數據在導入日志文件前就已經存在)。

所以,要測試下面的文件,每一次導入日志文件前,都必須先導入備份的數據庫

登陸mysql,使用命令

mysql > show bianry logs;

可以看到二進制日志的列表(由於我清理了全部的日志,所以現在只有一個日志)

圖片7

判斷當前的二進制文件

mysql > show master status \G

圖片8

該二進制文件存放在mysql的數據目錄中,如果直接查看該文件,會顯示亂碼。要使用mysqlbinlog命令才能正確顯示該文件。

[root@localhost data]# mysqlbinlog mysql-bin.000001

圖片9

我截取了該文件的最后一部分,留意上面箭頭所指的時間,表明數據庫在2015年6月30日 15:47:28分執行了三條語句:

COMMIT;

DELIMITER;

ROLLBACK;

然后我登陸數據庫,插入了一條數據,再查看這個日志內容:

圖片10

可以看到,日志文件增長了, 並在15:48:37產生了一條插入語句,而這條語句就是我使用的語句。因此可見,這個二進制日志完全記錄了對數據庫的所有操作。

 

使用mysqlbinlog命令來執行日志文件中的SQL語句

shell > mysqlbinlog binlog_files | mysql -u root -p

我在數據庫里不小心寫了一條刪除語句,我現在要恢復執行這條語句之前的數據庫狀態,該怎樣做呢?

首先,把日志文件內容另存為一個可閱讀的文件

[root@localhost data]# mysqlbinlog mysql-bin.000002 > tmpfile

[root@localhost data]# vi tmpfile

然后找到該文件中的那條刪除數據的語句並刪除該語句

圖片11

在上圖中可以看到在2015年6月30日15:49:38執行了一條delete語句,現在刪除該語句,保存並退出

記住:首先導入之前的備份數據庫,然后再把這個文件導入到mysql服務器中

shell > mysql < lastest-backup.sql

shell > mysql -uroot -p < tmpfile

就可以看到被刪除的數據出現了

如果要導入多個二進制日志,最好不要單獨到導入每一個日志,譬如要導入兩個日志。

shell > mysqlbinlog mysql-bin.000001 | mysql -u root -p

shell > mysqlbinlog mysql-bin.000002 | mysql -u root -p

上面的做法是有風險的,假如第一個日志中含有CREATE TABLE語句,而第二個日志中含有USE語句,當第一個日志導入進程失敗時也會導致第二個日志導入失敗(因為建表語句執行失敗,所以導入第二個日志時就沒有表)

為了避免出現這種錯誤,可以把多個日志一次性導入

shell > mysqlbinlog mysql-bin.000001 mysql-bin.000002 | mysql -u root -p

另一個方法如下

shell > mysqlbinlog mysql-bin.000001 > /tmp/tmpfile

shell > mysqlbinlog mysql-bin.000002 >> /tmp/tmpfile

shell > mysql -uroot -p -e “source /tmp/tmpfile;”

使用-e選項可以不登陸數據庫,直接運行雙引號里的語句

使用時間點來恢復數據

使用日志文件可以很明確地指出把數據恢復到哪個時間點。正如我上面舉的例子,在上圖中可以看到在2015年6月30日15:49:38執行了一條delete語句,但是我當時並沒有發現,在我又執行了很多語句之后才發現了這個巨坑。此時,我該如何挽救呢?

1. 首先,我要先導入之前備份的最新的數據庫

shell > mysql < lastest-backup.sql

2. 把日志文件導出到一個可以閱讀的文件中

shell > mysqlbinlog mysql-bin.000002 > /tmp/tmpfile

3. 打開該文件,找到delete語句執行時候的時間點(如上一張圖所示)

4. 然后在導入日志文件時,只執行到2015年6月30日15:49:38之前的語句

shell > mysqlbinlog --stop-datetime="2015-06-30 15:49:37" \

      mysql-bin.000002 | mysql -u root -p

注意,--stop-datetime要指向前一個時間

5. 再一次導入日志文件,這次只執行從2015年6月30日15:49:38之后的語句

shell > mysqlbinlog --start-datetime="2015-06-30 15:50:11" \

      mysql-bin.000002 | mysql -u root -p

注意,--start-datetime要指向后一個時間

注意:

  1. 其實刪除該日志文件的那條delete語句,然后導入到mysql中會更簡單,不過這里為了演示如何指定使用時間點來恢復數據
  2. 指定時間點來恢復數據其實並不好用,因為可能會有多條語句在同一個時間里執行,這個方法就完全不管用了,可以參考下面使用事件點來恢復數據。

使用事件點來恢復數據

圖片12

留意上圖所指的at 508,這個文件中的所有跟在at后面的數字就是事件點,這個數字是遞增且唯一的。

所以,先恢復到這個事件點之前

shell > mysqlbinlog --stop-position=411 \

      mysql-bin.000001 | mysql -u root -p

同樣地,往前移一個點

再恢復從這個事件點之后的數據

shell > mysqlbinlog --start-position=627 \

      mysql-bin.000001 | mysql -u root -p

往后移一個時間點

 

自動化備份

自動執行備份腳本

寫好備份腳本后,通過把腳本添加到contrab中就能實現自動備份。

1. 確認crond服務正在運行

[root@FirstCentOS backup]# service crond status

圖片13

如果沒有啟動,則使用命令啟動:

[root@FirstCentOS backup]# service crond start

2. 然后把腳本添加到contrab中(每天01:00自動備份)

[root@FirstCentOS backup]# crontab -e

#backup all databases in mysql on 01:00 everyday by root

00 01 * * * /bin/sh /server/backup/backup_automatically.sh >/dev/null 2>&1

把上面那行的內容添加進去,然后保存退出即可

 

上傳到ftp

我們每天執行一次備份,時間長了之后就會產生大量的文件,浪費磁盤空間,所以可以在每天備份的時候就自動把備份文件上傳到ftp上,然后刪除本地磁盤的文件,就能節省本地磁盤的空間。

1. 我是參考這篇文章在windows上搭建的ftp服務器:http://jingyan.baidu.com/article/63f23628f04e420209ab3d70.html

2. 然后在linux上安裝ftp

[root@FirstCentOS backup]# yum install ftp -y

3. 測試上傳能否成功

[root@FirstCentOS backup]# ftp -i -n <<EFO

open 192.168.1.205              #ftp的ip地址

user Administrator 123456        #用戶名和密碼

cd mysql                      #上傳到ftp的哪個文件夾上

lcd /server/backup               #要上傳的文件的路徑

hash

binary        

put 2015-07-07.tar.bz2            #上傳的文件名

prompt

close

bye

EFO

注意上面的binary選項,非常重要,因為從linux上傳文件到windows的服務器中會改變格式,而binary選項能保證不改變任何格式

下載文件:

[root@FirstCentOS backup]# ftp -i -n <<EFO

open 192.168.1.205              #ftp的ip地址

user Administrator 123456        #用戶名和密碼

cd mysql                      #要下載的文件位於ftp的哪個文件夾上

binary        

get 2015-07-07.tar.bz2            #要下載的文件名

close

bye

EFO


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM