數據備份:將源數據再次存儲到新的位置
數據恢復:將備份好的數據重新應用到數據庫系統
常見的備份類型:
a.按照是否備份整個數據集來分
完全備份:備份從開始到執行備份這一時刻的所有數據集
增量備份:備份從上次備份到這次備份時刻變化的數據集
差異備份:備份從上一次完全備份到這一備份時刻變化的數據集
b.按照備份的數據庫對象來分
物理備份:通過複製數據集在文件系統中的文件來備份
邏輯備份:在數據庫的客戶端工具上使用SQL語句,應用程序或其他腳本文件做備份的操作
c.按照備份時,還能提供的服務分類
熱備份:備份的過程中,可以對備份的數據集做讀寫操作
溫備份:備份的過程中,只能對備份的數據集只能做讀操作,不可有寫操作
冷備份:備份的過程中,直接將服務下線,讀寫操作均無法執行
4. 備份的數據內容:
1.數據;
2.二進制日誌
3.InnoDB存儲以前的事務日誌文件;
4.代碼——存儲過程,存儲函數,觸發器,事件調度器等;
5.當前服務器上用於啓動數據服務是所使用的配置文件;
6.操作系統上與MySQL或MariaDB相關的配置——sudo任務、cron任務等;
常用的備份數據的方法:
1)使用select語句導出數據做備份,然後使用load data命令做數據恢復
備份類型:因爲是使用SQL語句做備份的,所以是溫備份
備份語句:SELECT ..... INTO OUTFILE "file_name" [FIELDS TERMINATED BY 'string'] [ENCLOSED BY 'char'] [ESCAPED BY 'char'] ] [LINES [STARTING BY 'string'] [TERMINATED BY 'string']]
數據導入語句(數據恢復):LOAD DATA INFILE “/path/file_name” INTO TABLE table_name [FIELDS TERMINATED BY 'string'] [ENCLOSED BY 'char'] [ESCAPED BY 'char'] ] [LINES [STARTING BY 'string'] [TERMINATED BY 'string']]
FIELDS各選項內容
TERMINATED BY 'string' :指定導出或者導入時的字段分隔符
ENCLOSED BY 'char' :指定導入或導出時的引用符號
ESCAPED BY 'char' :定義轉義字符默認是 \
LINES各選項內容
STARTING BY 'string':指定行的起始符號,默認不指定
TERMINATED BY 'string':指定行的分隔符,默認換行符
數據備份恢復實例:
MariaDB [hellodb]> lock tables students read; 給表添加讀鎖,以免在做數據備份的時候,數據發生變化 MariaDB [hellodb]> select * from students into outfile "stud.txt"; //將students表內的所有內容,備份,放到stud.txt文件中 Query OK, 25 rows affected (0.01 sec) 因爲此次操作在hellodb數據庫中做的,所以默認文件將會創建在hellodb數據庫下的stud.txt文件中 查看stud.txt文件內的內容 MariaDB [hellodb]> unlock tables; 釋放鎖 [root@bogon ~]# cat /var/lib/mysql/hellodb/stud.txt 1 Shi Zhongyu 22 M 2 3 2 Shi Potian 22 M 1 7 3 Xie Yanke 53 M 2 6 4 Ding Dian 32 M 4 4 5 Yu Yutong 26 M 3 1 6 Shi Qing 46 M 5 7 7 Xi Ren 19 F 3 9 8 Lin Daiyu 17 F 7 5
MariaDB [hellodb]> delete from students; //清除students表中的數據 MariaDB [hellodb]> select * from students; //查看students表中是否有數據 Empty set (0.00 sec) MariaDB [hellodb]> load data infile "/var/lib/mysql/hellodb/stud.txt" into table students; //做數據恢復,使用的文件請用絕對路徑 Query OK, 25 rows affected (0.09 sec) Records: 25 Deleted: 0 Skipped: 0 Warnings: 0 MariaDB [hellodb]> select * from students; //再次查看錶 +-------+---------------+-----+--------+---------+-----------+ | StuID | Name | Age | Gender | ClassID | TeacherID | +-------+---------------+-----+--------+---------+-----------+ | 1 | Shi Zhongyu | 22 | M | 2 | 3 | | 2 | Shi Potian | 22 | M | 1 | 7 | | 3 | Xie Yanke | 53 | M | 2 | 6 |
注意:1.這種備份操作,屬於邏輯備份和溫備份,備份時需要提前給表施加讀鎖;
2.使用select導出數據,只會導出數據,但不會導出表的格式,所以當我們使用load data導入數據時,要保證表存在,且表結構與之前相同,所以這種備份只能做表數據備份恢復,
MariaDB [hellodb]> alter table students drop TeacherID; //刪除最後一個字段 MariaDB [hellodb]> load data infile "/var/lib/mysql/hellodb/stud.txt" into table students; Query OK, 25 rows affected, 25 warnings (0.01 sec) Records: 25 Deleted: 0 Skipped: 0 Warnings: 25 MariaDB [hellodb]> select * from students; +-------+---------------+-----+--------+---------+ | StuID | Name | Age | Gender | ClassID | +-------+---------------+-----+--------+---------+ | 1 | Shi Zhongyu | 22 | M | 2 | | 2 | Shi Potian | 22 | M | 1 | | 3 | Xie Yanke | 53 | M | 2 | | 4 | Ding Dian | 32 | M | 4 | 做恢復時,會有警告,但是不影響前面幾個字段的數據恢復,最後一個字段無法恢復 MariaDB [hellodb]> alter table students drop Name;刪除中間字段 MariaDB [hellodb]> load data infile "/var/lib/mysql/hellodb/stud.txt" into table students; Query OK, 25 rows affected, 100 warnings (0.01 sec) Records: 25 Deleted: 0 Skipped: 0 Warnings: 100 MariaDB [hellodb]> select * from students; +-------+-----+--------+---------+ | StuID | Age | Gender | ClassID | +-------+-----+--------+---------+ | 1 | 0 | | 0 | | 2 | 0 | | 0 | | 3 | 0 | | 0 | | 4 | 0 | | 0 | | 5 | 0 | | 0 | | 6 | 0 | | 0 | 出現警告,但數據恢復操作執行完成,但是由於多個字段間數據類型等不一致,會導致表數據無法正常恢復; 刪除表操作 MariaDB [hellodb]> drop table students; Query OK, 0 rows affected (0.04 sec) MariaDB [hellodb]> load data infile "/var/lib/mysql/hellodb/stud.txt" into table students; ERROR 1146 (42S02): Table 'hellodb.students' doesn't exist 會顯示錯誤,表不存在無法恢復
3.當我們使用哪個數據庫做數據導出時,其導出的文件會默認存在該數據庫的目錄下;當然我們可以使用變量 secure_file_priv修改保存路徑,但是此變量是隻讀變量;
4.若我們導出的數據內容,變換了默認格式,則在導入的時候也應該使用相同的格式導入,否則表內容出錯;
MariaDB [hellodb]> select * from hellodb.students into outfile "students1.txt" fields terminated by ":"; //導出數據時,變換默認的分隔符 Query OK, 25 rows affected (0.02 sec) [root@bogon ~]# cat /var/lib/mysql/hellodb/students1.txt 1:Shi Zhongyu:22:M:2:3 2:Shi Potian:22:M:1:7 3:Xie Yanke:53:M:2:6 4:Ding Dian:32:M:4:4 5:Yu Yutong:26:M:3:1 導入時,不變換分隔符 MariaDB [hellodb]> load data infile "/var/lib/mysql/hellodb/students1.txt" into table students; Query OK, 25 rows affected, 150 warnings (0.02 sec) Records: 25 Deleted: 0 Skipped: 0 Warnings: 150 MariaDB [hellodb]> select * from students; +-------+------+-----+--------+---------+-----------+ | StuID | Name | Age | Gender | ClassID | TeacherID | +-------+------+-----+--------+---------+-----------+ | 1 | | 0 | | NULL | NULL | | 2 | | 0 | | NULL | NULL | | 3 | | 0 | | NULL | NULL | | 4 | | 0 | | NULL | NULL |
5.在做數據導入,可以使用mysqlimport命令
用法mysqlimport [options] db_name textfile1
[root@bogon ~]# mysqlimport -d hellodb /var/lib/mysql/hellodb/students.txt hellodb.students: Records: 25 Deleted: 0 Skipped: 0 Warnings: 0
mysqlimport原理和load data相同,只是執行方式不同
mysqlimport選項:
--fields-terminated-by=..., --fields-enclosed-by=..., --fields-optionally-enclosed-by=..., --fields-escaped-by=...
--lines-terminated-by=...
--use-threads=N:使用多mysql線程實現併發導入;
--lock-tables, -l:給表施加鎖;
--local, -L:讀取客戶端本地的某文件,將其中的內容恢復之表中;
--ignore-lines=N:導入數據時忽略前N行記錄;
2)使用mysqldump工具做數據的備份和恢復;
此備份恢復是針對數據庫及數據庫中數據集做恢復的
格式:mysqldump [options] [db_name [tbl_name ...]]
shell> mysqldump [options] db_name [tbl_name ...]
shell> mysqldump [options] --databases db_name ...
shell> mysqldump [options] --all-databases
mysqldump原理:會將你要導出的表,或數據庫,寫成SQL語句並且標準輸出,此時需要我們用重定向,將這些內容,寫入一個新的文件之中,將文件後綴改爲.sql, 使得其可以在mysql之中運行,從而達到數據恢復的效果
簡單示例:
[root@bogon ~]# mysqldump hellodb students > stud.sql vim stud.sql
然後我們刪掉表並且做恢復
MariaDB [hellodb]> drop table students; Query OK, 0 rows affected (0.02 sec) MariaDB [hellodb]> \. stud.sql Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) ......
mysqldump的常用選項
連接選項:
-u, -h, -p, -P, -S, --protocol;用法和mysql相同
篩選選項:
--all-databases, -A 備份所有的數據庫
--databases, -B 指定需要備份的數據庫;一旦寫上此選項,則該選項後面的所有內容都被當成數據庫名稱,而且在輸出的文件中,每個數據庫前都會加上創建數據庫和use語句;
加--databases和不加--databases的區別 不加--databases ,不會創建數據庫,只會恢復其中的表,所以我們需要依賴一個指定的數據庫才行
加上--databases 會創建出數據庫,並且在創建數據庫之中創建相應的表
--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 ...
示例:導出某個數據的某個表 [root@bogon ~]# mysqldump --database hellodb students > hello.sql //若不加--tables 怎會將students表,當數據庫處理,顯然這不是數據庫,則報錯 mysqldump: Got error: 1049: "Unknown database 'students'" when selecting the database [root@bogon ~]# mysqldump --database hellodb --tables students > hello.sql 所以需要加一個--tables做分隔
--where=´where_condition´, -w ´where_condition´
指定篩選條件並導出表中符合篩選條件的數據;
如:--where='Name=James'
DDL選項:
--add-drop-database
在導出的數據文件中的每一個create databases語句前加上drop database if exists的語句先刪除指定的數據庫;
/*!40000 DROP DATABASE IF EXISTS `hellodb`*/; //會在創建數據庫前一行添加此行
--add-drop-table
在導出的數據文件中的每一個create table語句前加上drop table 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, and --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功能;
在MySQL的5.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, -x
爲所有的表施加一個一直持續到數據導出結束的全局讀鎖。該選項僅在數據導出開始時施加一次讀鎖,而該鎖鎖所有表且永久鎖,直到數據導出結束纔會釋放;
該選項開啓後會自動關閉--single-transaction和--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表更有用;
完整示例:
1.導出一個innodb引擎的表
[root@bogon ~]# mysqldump --database hellodb --no-create-db --tables students --single-transaction --flush-logs > hello.sql MariaDB [hellodb]> drop table students; //破壞數據 Query OK, 0 rows affected (0.04 sec)
2.做數據恢復
MariaDB [hellodb]> set @@sql_log_bin=0; Query OK, 0 rows affected (0.00 sec) MariaDB [hellodb]> \. hello.sql Query OK, 0 rows affected (0.00 sec) MariaDB [hellodb]> set @@sql_log_bin=1; Query OK, 0 rows affected (0.00 sec)
注意:
1.在做備份的時候,同樣需要我們給表施加鎖,面對MyISAM表我們添加--lock-tables,面對innodb表需要添加,--single-transaction
2.在做數據導出時,儘量添加--flush-logs選項,刷寫二進制日誌,這樣以後可以更方便的使用該二進制日誌做增量恢復;
3.在做數據恢復時,也會產生二進制日誌,但是這種日誌內容,是多餘的,我們可以手動關閉二進制日誌記錄功能,等待恢復完成後,再手動開啓
3)使用lvm2做備份恢復;
是物理備份,溫備份
備份原理:使用快照技術,將此事此刻的數據庫系統內容做標記,若數據庫某一內容發生變化,則將其原數據內容複製到快照空間中,沒發生變化的則不會做快照。
恢復原理:將快照後的內容保存到其他文件中,若數據庫丟失,則可以將快照的內容複製到數據庫目錄中,實現恢復;
具體操作:
1.添加新的磁盤(做快照方便)
爲其創建卷組,及邏輯卷,並格式化邏輯卷,建議文件系統類型爲ext4
pvcreate /dev/sdb vgcreate -s 16M testvg /dev/sdb lvcreate -L 10GiB -n testlv testvg mkfs -t ext4 /dev/testvg/testlv mkdir /data/mysql mount /dev/testvg/testlv /data/mysql/ //將做好的邏輯卷掛載到/data/mysql下
2.關閉mysql服務,修改mysql數據庫目錄爲新目錄,並將原來的數據庫內容複製一份到新數據庫目錄下
cp -a /var/lib/mysql/* /data/mysql/ chown -R mysql. /data/mysql/ 修改/etc/my.cnf(設置selinxu策略) [mysqld] datadir=/data/mysql 開啓服務
3.進入mysql交互命令中,施加全局鎖
MariaDB [(none)]> flush tables with read lock;
4.爲數據庫目錄創建快照,
lvcreate -s -L 1GiB -p r -n mysql_photo /dev/testvg/testlv 創建完成之後,解鎖 MariaDB [(none)]> unlock tables;
5.掛載快照,並將其內容複製出去,然後刪除快照
mount /dev/testvg/mysql_photo /mydata/photo/ cp -a /mydata/photo/* /mysql/
6.做數據恢復(線下恢復),所以需要關閉mysql服務
[root@bogon ~]# systemctl stop mariadb.service [root@bogon ~]# cp -a /mysql/* /data/mysql/ [root@bogon ~]# chown -R mysql. /data/mysql/ 修改權限 [root@bogon ~]# systemctl start mariadb.service 啓動服務 [root@bogon ~]# mysql -S /data/mysql/mysql.sock連接數據庫
注意:快照恢復是物理備份,和完全備份,若想實現對快照後數據變化的恢復,則需要我們使用二進制日誌文件
4)使用xtrabackup工具做恢復
物理備份
對MyISAM引擎的表做溫備份(施加全局鎖,或備份鎖)
對innodb引擎的表做熱備份(備份並監控redo log,在其備份期間若redo log還在變化,則會將變化的內容寫入緩存,並依次備份,等備份結束還會對備份內容重寫,實現熱備份)
步驟:
備份過程:備份redo log文件以及獲取二進制文件座標點,並做備份
準備過程:若引擎是innodb,則對備份好的redo log文件做檢測,主要是對一些事物,實現前滾或回滾
恢復過程:物理恢復,需要關閉服務
語法:
innobackupex [options] /path/file
option:
連接選項:
--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:在實施增量備份時,用於指定增量備份的參考目錄;
innobackupex /ttt ...... 180804 05:45:17 completed OK! [root@bogon ~]# ll /ttt/ 總用量 4 drwx------. 12 root root 4096 8月 4 05:45 2018-08-04_05-45-15 默認完全備份
增量備份
[root@bogon 2018-08-04_05-52-36]# innobackupex --incremental --incremental-basedir /ttt/2018-08-04_05-45-15 /ttt //基於完全備份的目錄做增量備份
準備(需要安照步驟依次準備):每次準備都會把增量內容添加到完全備份上
[root@bogon ttt]# innobackupex --apply-log --redo-only /ttt/2018-08-04_05-45-15/ /完全備份準備 innobackupex --apply-log --redo-only /ttt/2018-08-04_05-45-15/ --incremental-dir /ttt/2018-08-04_05-52-36/ //增量備份準備 完全備份目錄 增量備份目錄
恢復:(需要停止mysql服務,並且保證datadir下爲空),否則報錯
Original data directory /var/lib/mysql is not empty!
[root@bogon ttt]# innobackupex --copy-back /ttt/2018-08-04_05-45-15/ //恢復只需要寫完全備份目錄 [root@bogon ttt]# chown -R mysql. /var/lib/mysql/ //修改權限
啓動服務即可;