1. 程式人生 > >MySQL/MariaDB的數據備份與恢復

MySQL/MariaDB的數據備份與恢復

快速 ans col complete 文字 磁盤 databases 自動激活 comm

MySQL/MariaDB的數據備份與恢復

1. 什麽是數據備份與數據恢復?

1) 數據備份:已有數據的副本;

2) 數據恢復:將副本和二進制日誌的內容重新應用到線上系統;


2. 為什麽要進行數據備份與恢復?

主要用於防止災害的發生,可進行災難恢復,有多種災難可能對數據造成破壞:如:自然災害,

hacker attack,計算機本身硬件老化,軟件故障(如:BUG,惡意代碼等),操作人員誤操作(如:誤刪除);


3. 備份有哪些類型?

按照是否備份整個數據集分類:

1)全局備份 :備份從起始到執行備份操作時的所有數據內容;

2)增量備份 :備份從上一次完全備份或增量備份以來變化的數據;

3)差異備份 :備份從上一次完全備份以來變化的數據;


按照備份的數據庫對象分類:

1)物理備份 :通過復制數據文件進行數據備份;

2)邏輯備份 :在數據庫的操作接口上利用SQL語句,腳本或應用程序將數據零存在一個或多個文件中;


按照備份時是否能夠提供服務分類:

1)熱備份 :在數據讀寫均可進行的狀態下進行的備份操作;

2)溫備份 :在數據可讀不可寫的狀態下進行的備份操作;

3)冷備份 :在數據讀寫皆不可進行(服務離線)的狀態下進行的操作;


4. MySQL/MariaDB提供的備份工具:

1)SELECT語句(導出數據)和LOAD DATA語句(導入數據);

2)mysqldump命令(mysql自帶的備份工具); 註意:備份時,MySQL服務需在線;

3)cp/scp/dd/tar/cpio命令;

4)lvm2或Btrfs快照;

5)mysqlhotcopy命令(不常用,即將廢棄);

6)Percona Xtrabackup工具;



1)利用SELECT語句和LOAD DATA語句導入導出數據:

SELECT語句語法:

SELECT [INTO OUTFILE 'file_name'[CHARACTER SET charset_name] export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]


LOAD DATA語句語法:

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[CHARACTER SET charset_name]
[{FIELDS | COLUMNS}
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
[IGNORE number {LINES | ROWS}]
[(col_name_or_user_var,...)]
[SET col_name = expr,...]


1. FIELDS [TERMINATED BY 'string']: 用於指定導入或導出時的字段分隔符;
2. FIELDS [[OPTIONALLY] ENCLOSED BY 'char']:用於指定導入或導出時的字段引用符號;
如果指定看OPTIONALLY,則只用在字符串和日期時間類型的數據字段上;默認未指定;
3. FILEDS [ESCAPED BY 'char']:指定轉義字符;

4. LINES [STARTING BY 'string']:指定行的起始符號,默認未定義;
5. LINES [TERMINATED BY 'string']:指定行的結束分隔符,默認是“\n”;

註意:
‘char’表示只能使用一個字符,‘string’表示可指定多個字符;


一般情況下,SELECT語句和LOAD DATA語句是配套使用的,SELECT按照一定規則檢索出數據至指定文件中,

LOAD DATA語句將SELECT導出的數據重新導入數據庫:


前提:建議將二進制日誌的功能開啟

]# vim /etc/my.cnf

[mysqld]

log_bin=binlog


示例;

    MariaDB [hellodb]> select * from hellodb.students into outfile "students.bak" lock in share mode;

將hellodb數據庫中的students數據表導出到名為students.bak的文件中,導出過程中將表鎖定;

鎖定的目的是防止在導出表的過程中有其他會話對表進行修改,導致數據變化,前後數據不一致;

students.bak文件默認存儲在數據目錄(/var/lib/mysql)下;


    MariaDB [(none)]> truncate hellodb.students;
    ...
    MariaDB [(none)]> select * from hellodb.students;
    Empty set (0.00 sec)

假如students數據表被誤刪除,檢索發現為空表;


   MariaDB [(none)]> load  data infile "/var/lib/mysql/students.bak" into table hellodb.students;
   MariaDB [(none)]> use hellodb;
   MariaDB [hellodb]> select * from students;
   。。。。
   27 rows in set (0.00 sec)

將hellodb數據庫中被誤刪除的students數據表重新導入hellodb數據庫,完成後,檢索存在;


這樣就完成了一次數據的備份與恢復操作;




2)mysqldump命令:
用於導出數據庫或數據庫中的數據集,並可以在其它的非MySQL數據庫中進行導入,因此,也可用來做數據遷移;

格式: mysqldump [options] [db_name [tbl_name ...]]
shell> mysqldump [options] db_name [tbl_name ...]
shell> mysqldump [options] --databases db_name ...
shell> mysqldump [options] --all-databases


常用選項:
連接選項: -u , -h ,-p ,-P , -S , --protocol ;
篩選選項:
--all-databases, -A
指定mysqldump備份所有的數據庫;
--databases, -B
指定需要備份的數據庫;一旦寫上此選項,則該選項後面的所有內容都被當成數據庫名稱,

而且在輸出的文件中,每個數據庫前都會加上創建數據庫和use語句;
--ignore-table=db_name.tbl_name
導出時忽略指定的數據庫中的指定表,同時也可以用戶忽略視圖;每個此選項僅能帶一個參數,

因此想要忽略多個表則需給出多個此選項;
--no-data, -d
在備份時不導出任何數據內容,僅導出表結構;
--routines, -R
導出存儲函數和存儲過程,但不會導出他們的屬性值;
--events, -E
導出事件調度器
--triggers
導出觸發器,默認開啟,想要關閉可以使用--skip-triggers選項;
--tables
覆蓋了--databases選項,使得其後面所有的參數都被當做表名處理;使用了此選項,

每次mysqldump僅能導出一個庫中表的數據;
格式為:--tables db_name tbl_name1 tbl_name2......--where=′where_condition′, -w ′where_condition′
指定篩選條件並導出表中符合篩選條件的數據;
如:--where='Name=james'

DDL選項:
--add-drop-database
在導出的數據文件中的每一個create databases語句前加上drop database if exists的語句先刪除指定的數據庫;
--add-drop-table
在導出的數據文件中的每一個create tables語句前加上drop database if exists的語句先刪除指定的表,

默認開啟此功能;
--no-create-db, -n
在使用了--databases或--all-databases選項時,在導出的文件中加會加上創建數據庫的語句;而一旦使用此選項,

前面兩個選項功能會被抑制;
--no-create-info, -t
不會在導出的文件中添加創建表的語句;
--replace
所有向表中添加數據的操作語句均被替換成REPLACE語句,而不是INSERT語句;

字符集選項:
--default-character-set=charset_name
在導出數據的過程中,指定導出時使用的字符集;

此選項有時很重要,遷移數據的目標主機上和當前服務器的字符集如果不相同,可能會導致亂碼,

默認為“utf8”;
--set-charset
在導出的數據結果中加上SET NAMES statement語句,默認此功能開啟;關閉可使用的選項:

--skip-set-charset;

與主從復制相關的選項
--delete-master-logs
在執行了一次dump操作後,會向主服務器發送一個PURGE BINARY LOGS statement,

以刪除其二進制日誌;並會自動激活--master-data選項的功能;
--master-data[=value]
該選項主要用來建立一個復制操作;
值為1時,導出的數據文件中會記錄CHANGE MASTER語句;
值為2時,導出的數據文件中會記錄CHANGE MASTER語句;但該語句被註釋;默認值無任何值,

意味著在導出的數據文件中不會記錄CHANGE MASTER語句;

在使用此選項時,會自動忽略--lock-tables選項;
當使用了--single-tranaction選項時,也會自動激活--lock-all-tables;

格式化選項:
--compact
緊湊格式輸出,即:簡化輸出的內容,幾乎所有的註釋類內容都不會被輸出到文件中;
相當於: --skip-add-drop-table, --skip-add-locks, --skip-comments,--skip-disable-keys,

--skip-set-charset 選項的組合;
--complete-insert, -c
在INSERT語句中加入各個被操作的列的名稱;
--tab=path, -T path
將每個表的結構定義用的SQL語句和表中存儲的數據內容,分別導出到指定的目錄中,

使用不同的文件進行保存;其中TBL_NAME.sql文件存放表的定義格式,

TBL_NAME.txt文件存放表中的數據;在導出數據內容的時候,相當於
使用了SELECT ... OUTFILE 'tbl_name.txt'語句,默認的字段分隔符就是“\t”;

使用此選項操作時,必須要有一個前提條件:client和server必須是同一臺主機,

且mysql用戶對指定的目錄要有寫權限,同時連接數據庫的用戶必須有FILE權限;

而且還要求不能和--databases或--all-databases選項一起使用;

--fields-terminated-by=..., --fields-enclosed-by=..., --fields-optionally-enclosed-by=..., --fields-escaped-by=...,

--lines-terminated-by=... 選項可以在此時應用,用於指定各種分隔符;

--quote-names, -Q
引用表名或列名時,使用任何引用符號,默認的引用符號為反向單引號,即`;


性能選項:
--delayed-insert
在非事務型存儲引擎管理的表中,在INSERT操作時可支持DELAYED功能;在MySQL5.6.6開始被廢棄;
--disable-keys, -K
在INSERT語句前後加上禁用和啟用索引的語句;
在大量的數據插入時,此選項很有用,默認是開啟的;
--insert-ignore
使用INSERT IGNORE語句代替INSERT語句;
--quick, -q
快速導出數據,在導出大表時非常有用;
默認導出數據時會一次性檢索表中所有數據並加入到內存中,而使用該選項則是檢索一行導出一行;


加鎖和事務有關的選項:
--add-locks
在INSERT語句前後加上LOCK TABLES和UNLOCK TABLES語句,默認開啟;
--flush-logs, -F
在開始導出數據前事先刷寫二進制日誌(二進制日誌手動的滾動);
如果使用了--all-databases選項,則依次在各個數據庫之前都會執行FLUSH LOGS;
如果使用 --lock-all-tables 或 --master-data選項,則刷寫日誌僅執行一次,等價於FLUSH TABLES WITH READ LOCK,
鎖定所有表,保證數據一致性;
--flush-privileges
在導出所有數據庫之後在數據文件的結尾加上FLUSH PRIVILEGES語句;
一般會在導出mysql庫或者依賴於mysql庫時都應該使用此選項;
--lock-all-tables,
為所有的表施加一個一直持續到數據導出結束的全局讀鎖。該選項僅在數據導出開始時施加一次讀鎖,

而該讀鎖鎖定所有表,直到數據導出結束後才會釋放;
該選項開啟後會自動關閉--single-transaction and --lock-tables選項;
--lock-tables, -l
在導出每個數據庫的數據之前依次對該數據庫中所有表施加讀鎖(多次的鎖施加的過程),

對於非事務型的存儲引擎(如:MyISAM)的表可以進行並行鎖操作;但對於事務型存儲引擎

(如:InnoDB)的表來說,使用--single-tranaction選項更好, 因為InnoDB無需完全讀鎖;
--single-transaction
該選項在導出數據前將設置一個事務,且隔離級別為REPEATABLE-READ,

並且同時發送一個START TRANSACTION語句給服務器端;
該選項在導出InnoDB存儲引擎的表時非常有用,一旦開啟事務,則意味著數據庫會有一致性和持久性的安全保護,
不會阻塞任何其它會話或線程的數據處理;
--no-autocommit
在INSERT語句前後加上SET @@autocommit=0及SET @@autocommit=1語句,

並且在需要提交事務時添加COMMIT語句;
--order-by-primary
如果被導出的表中存在主鍵索引或唯一鍵索引,則排序後按照順序導出數據;
對於導出MyISAM表比導出InnoDB表更有用;



示例:

新建一個目錄用於存放備份的數據:

  [root@bogon ~]# mkdir /mysql-bak


對數據庫hellodb進行備份:

[root@bogon ~]# mysqldump --single-transaction --flush-logs --master-data=2 --databases hellodb > /mysql-bak/hellodb1.sql
[root@bogon ~]# mysqldump --single-transaction --flush-logs --master-data=1 --databases hellodb > /mysql-bak/hellodb2.sql
[root@bogon ~]# mysqldump --single-transaction --flush-logs --master-data=0 --databases hellodb > /mysql-bak/hellodb3.sql


對三個文件進行對比:--master-data=0時沒有下圖語句;

[root@bogon ~]# vim /mysql-bak/hellodb1.sql

技術分享圖片


[root@bogon ~]# vim /mysql-bak/hellodb2.sql

技術分享圖片


如果hellodb數據庫因某些因素遭到破壞:

  MariaDB [hellodb]> drop databases hellodb;

技術分享圖片


恢復數據:

  MariaDB [hellodb]> set @@sql_log_bin=0;
  MariaDB [hellodb]> \. /mysql-bak/hellodb1.sql
  MariaDB [hellodb]> set @@sql_log_bin=1;


檢測是否恢復成功:

技術分享圖片

技術分享圖片


數據庫恢復成功;


註意:使用mysqldump備份MyISAM表的時候,需要加上--lock-tables選項,以保證數據一致性;
如果使用--lock-all-tables,一次性鎖定所有表,影響的範圍比較大;


mysqldump使用的建議:
1.從性能考慮:
在需要導出大量數據的時候,建議使用--quick選項加速數據導出,但導入速度不變。
如果導入的是innodb存儲引擎的表中的數據,加上--no-autocommit選項,可以極大的提高性能;

2.從數據一致性角度考慮:
對於innodb表,必選的選項是--single-transaction,對於MyISAM表,使用--lock-tables是必須的,

但有時使用--lock-all-tables速度更快;
既有MyISAM表又有InnoDB表時,可以分別導出;這樣既能保證數據一致性,又可以保證數據導出的效率;

3.從方便管理和方便維護角度考慮:
在任何數據導出之前,FLUSH LOGS都非常有必要,需要加上--flush-logs選項;

同時會根據導出的數據表使用的存儲引擎的不同,配合添加--lock-all-tables或--single-transaction選項;
如果有主從關系,主服務器上的數據導出是為了從服務器上數據快速同步,需要使用--master-data=2,

這樣就可以方便地知道二進制日誌中應用到了哪個二進制日誌文件的哪個位置坐標,可以方便定位;

4.從字符集兼容角度考慮:
如果表中涉及到了中文字符,在導出日誌時,一定要設置字符集與該表的字符集一樣,

以避免mysqldump使用其默認的字符集, 使得數據恢復後出現亂碼;

5.其它因素:
導出數據的過程中和恢復數據的過程中都會產生二進制日誌,但現在這樣的二進制日誌是多余沒必要的。

應該在操作之前,關閉二進制日誌記錄功能,完成之後再開啟;



3)基於lvm2或btrfs的快照卷實現數據備份:

準備操作:給系統添加一塊硬盤,並重讀磁盤,讓其生效:

    [root@bogon ~]# echo '- - -' /sys/class/scsi_host/host0/scan


1. 創建一個目錄/data/mydata用作MySQL的數據目錄

並將源數據目錄下的所有內容復制到該目錄:

      [root@bogon ~]# mkdir -pv /data/mydata
      [root@bogon ~]# chown -R mysql:mysql /data/mydata
      [root@bogon ~]# cp -a /var/lib/mysql/* /data/mydata
      [root@bogon ~]# systemctl stop mariadb.service
      [root@bogon ~]# vim /etc/my.cnf
                      [mysqld]
                      datadir=/data/mydata
                      socket=/data/mydata/mysql.sock
                      ...
      [root@bogon ~]# setenforce 0
      [root@bogon ~]# systemctl start mariadb.service


2.創建物理卷,卷組及邏輯卷,並將邏輯卷格式化並掛載至/data/mydata:

    [root@bogon ~]# pvcreate /dev/sdb
    [root@bogon ~]# vgcreate -s 20M myvg /dev/sdb
    [root@bogon ~]# lvcreate -L 10GiB -n mydata myvg
    [root@bogon ~]# mkfs -t ext4 /dev/myvg/mydata
    [root@bogon ~]# mount /dev/myvg/mydata /data/mydata


3. 施加全局讀鎖,保證數據一致性:

   MariaDB [hellodb]> flush tables with read lock;

4. 記錄二進制日誌最後一個事件結束的位置標誌並讓日誌滾動:

技術分享圖片

   MariaDB [hellodb]> flush logs;

技術分享圖片


5.創建快照卷

   [root@bogon ~]# lvcreate -L 200M -s -p r  -n mydata_snapshot /dev/myvg/mydata

6.釋放全局讀鎖:

   MariaDB [hellodb]> unlock tables;

7. 創建掛載點,將快照掛載:

   [root@bogon ~]# mkdir /mnt/mydata
   [root@bogon ~]# mount /dev/myvg/mydata_snapshot /mnt/mydata

8. 拷貝快照卷內容至指定目錄並卸載邏輯卷:

   [root@bogon mysql]# mkdir /ytc
   [root@bogon mysql]# cp -a /mnt/mydata/* /ytc/
   [root@bogon mysql]# umount /mnt/mydata

9.暴力刪除數據內容:

停止服務,摘除磁盤,卸載邏輯卷

  [root@bogon mysql]# systemctl stop mariadb
  [root@bogon mysql]# umount /data/mydata

10.恢復數據,並啟動服務:

  [root@bogon mysql]# cp -a  /ytc/* /data/mydata/
  [root@bogon mysql]# chown -R mysql:mysql /data/mydata/
  [root@bogon mysql]# systemctl start mariadb.service



4)使用XtraBackup工具完成數據的備份和恢復:

Xtrabackup備份的原理:

備份:backup,使用物理備份方式,復制文件系統中的與指定庫或指定表相關的文件;
註意:xtrabackup在備份時,先備份InnoDB的表,再備份其他非InnoDB的表;
準備:prepare,由於備份的時候復制走的數據文件可能存在不一致數據,通過此階段保證數據一致;
恢復:copy back,用備份的結果集和對應的二進制日誌文件恢復被損壞或丟失的數據內容;



安裝xtrabackup:

  [root@bogon ~]# yum install percona-xtrabackup



使用xtrabackup工具進行數據備份和恢復:
innobackupex命令(xtrabackup)
用法:innobackupex | xtrabackup [--defaults-file=#] { --backup | --prepare | --copy-back } [Options] [Args]
常用選項:
連接選項:
--user=USERNAME
--host=HOSTNAME
--port=PORT
--password=PASSWORD
--socket=SOCKET_FILE_NAME
功能選項:
--backup:實施數據備份過程;
--prepare:實施準備過程;
--copy-back:實施數據恢復過程;
--apply-log:在準備過程中,用於應用redo log;
--redo-only:在準備過程中,僅應用redo log;
--incremental:在數據備份的過程中,實施增量備份;
--incremental-basedir:在實施增量備份時,用於指定增量備份的參考目錄;


完全備份:
除了必須給定連接MySQL服務所需要的連接選項,通常只需要給定一個備份的目標目錄即可;

語法:
innobackupex --user=USER --host=HOST --password=PASSWORD

--socket=PATH_TO_SOCK_FILE /PATH/TO/BACKUP_DESTINATION_DIR


示例:

創建一個目錄/ytc1/backup用來做備份目錄:

  [root@bogon ~]# mkdir -pv /ytc1/backuo


備份:

  [root@bogon ~]# innobackupex --socket=/var/lib/mysql/mysql.sock /ytc1/backup

查看:

技術分享圖片


恢復操作:

關閉服務後,將拷貝的數據拷貝回來即可,最後開啟服務;






MySQL/MariaDB的數據備份與恢復