數據庫的備份與恢復也是系統運維工程師必備的技能之一,下面介紹幾種mysql數據庫備份工具及其實現。
一、mysqldump備份恢復實例
二、爲數據文件所在邏輯卷創建快照卷的方式進行備份恢復實例
三、使用Xtrabackup進行增量備份和恢復實例
mysqldump:
可以把整個數據庫裝載到一個單獨的文本文件中。這個文件包含有所有重建您的數據庫所需要的SQL命令。這個命令取得所有的模式,並且將其轉換成DDL語法(CREATE語句,即數據庫定義語句),取得所有的數據,並且從這些數據中創建INSERT語句。這個工具將您的數據庫中所有的設計倒轉。因爲所有的東西都被包含到了一個文本文件中。這個文本文件可以用一個簡單的批處理和一個合適SQL語句導回到MySQL中。可以備份整個服務器、單個或部分數據庫,單個或部分表,以及表中的部分行;存儲過程、存儲函數、觸發器等,可以自動記錄備份時的二進制日誌文件以及相應的position;d於Innodb可以基於單事務模式進行熱備。
常用選項:
-A --all-databases 備份整個服務器
--add-drop-database 添加drop,防止報錯。
-C --compress,實現壓縮,用於網絡傳輸
-E --events ;備份時間調度器;
-R --routines;備份存儲過程和存儲函數;
-d --no-data;只備份表結構,不備份數據;
-B --databases ;指定單個或多個數據庫,以空格隔開;不指定默認備份整個數據庫服務器,不加此選項跟一個數據庫,則不會有創建此數據庫的語句,恢復時需自行創建;
備份之前先要請求讀鎖,可以使用選項:
-x, --lock-all-tables
如果只備份單張表,可以使用:
-l, --lock-tables
能夠記錄在備份時,記錄二進制日誌文件所處的位置;
--master-data=2
-- CHANGE MASTER TOMASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=1755;
在mysql中請求數據庫的讀鎖;
mysql> FLUSH TABLES WITH READ LOCK;
備份完成後,撤銷讀鎖:
mysql> UNLOCKTABLES;
對於InnoDB數據庫文件,還要注意觀察將buffer pool中的數據完全同步到數據庫中;(建議使用--single-transaction選項);
mysql> SHOW ENGINE InnoDB STATUS\G
在生產環境中注意觀察bufferpool和FILE I/O是否還有數據;
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated137363456; in additional pool allocated 0
Dictionary memoryallocated 62417
Buffer pool size 8191
Free buffers 7990
Database pages 200
Old database pages 0
Modified db pages 0
Pending reads 0
Pending writes: LRU 0,flush list 0, single page 0
Pages made young 0, notyoung 0
0.00 youngs/s, 0.00non-youngs/s
Pages read 154, created46, written 276
0.00 reads/s, 0.00creates/s, 0.00 writes/s
No buffer pool pagegets since the last printout
Pages read ahead0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 200, unzip_LRUlen: 0
I/O sum[0]:cur[0],unzip sum[0]:cur[0]
--------
FILE I/O
--------
I/O thread 0 state:waiting for i/o request (insert buffer thread)
I/O thread 1 state:waiting for i/o request (log thread)
I/O thread 2 state:waiting for i/o request (read thread)
I/O thread 3 state:waiting for i/o request (read thread)
I/O thread 4 state:waiting for i/o request (read thread)
I/O thread 5 state:waiting for i/o request (read thread)
I/O thread 6 state:waiting for i/o request (write thread)
I/O thread 7 state:waiting for i/o request (write thread)
I/O thread 8 state:waiting for i/o request (write thread)
I/O thread 9 state:waiting for i/o request (write thread)
Pending normal aioreads: 0 [0, 0, 0, 0] , aio writes: 0 [0, 0, 0, 0] ,
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync)log: 0; buffer pool: 0
296 OS file reads, 395OS file writes, 258 OS fsyncs
0.00 reads/s, 0 avgbytes/read, 0.00 writes/s, 0.00 fsyncs/s
--single-transaction
創建一個單一的應用於整個數據庫的事務,爲每一個Innodb的表創建一個快照,基於此快照來進行熱備份,不需要同時使用--lock-all-tables
開始備份:
# mysqldump -uroot -B db1 db2 -x > /backup/db1_db2_full-`date +%F`.sql
採用完全備份+增量備份的方式進行:
1、完全備份:
[root@localhost~]# mysqldump -uroot -p--single-transaction --events --master-data=2 --all-databases >/backup/alldb_full-`date +%F`.sql
[root@localhost ~]# ls/backup/
alldb_full-2013-09-07.sql
2、添加一些數據進行增量備份:
mysql> createdatabase db3;
ERROR 1223 (HY000):Can't execute the query because you have a conflicting read lock
mysql> unlocktables;
Query OK, 0 rowsaffected (0.00 sec)
mysql> create tablet1 (id int);
mysql> insert intot1 values (1),(2),(3);
查看二進制日誌中記錄的位置:
mysql> show masterstatus;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB |Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000004| 1993 | | |
+------------------+----------+--------------+------------------+
在alldb_full-2013-09-07.sql找到上次二進制日誌的最後的位置
-- CHANGE MASTER TOMASTER_LOG_FILE='mysql-bin.000004',MASTER_LOG_POS=1826;
[root@localhost ~]# mysqlbinlog--start-position=1826 --stop-position=1993 /mydata/data/mysql-bin.000004 >alldb_incre_`date +%F`.sql
在增加一些記錄:
mysql> create tabletb2 (identifier int);
Query OK, 0 rowsaffected (0.34 sec)
mysql> insert intotb2 values (1),(3),(5);
Query OK, 3 rowsaffected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
模擬數據庫出現故障,db3不小心被刪除
mysql> drop databasedb3;
Query OK, 2 rowsaffected (0.31 sec)
此時,該如何恢復:
1、恢復完全備份
2、恢復增量備份
3、將二進制日誌導出並恢復;
首先將二進制日誌導出
#找到刪除db3之前的位置:
[root@localhost ~]#mysqlbinlog /mydata/data/mysql-bin.000004
#130907 21:45:27 serverid 1 end_log_pos 2467 Xid = 3930
COMMIT/*!*/;
# at 2467
#130907 21:45:27 serverid 1 end_log_pos 2546 Query thread_id=8 exec_time=1 error_code=0
SETTIMESTAMP=1378561527/*!*/;
drop database db3
/*!*/;
DELIMITER ;
# End of log file
# 把從上次增量備份之後到db3刪除之前的二進制日誌導出到文件中;
[root@localhost ~]#mysqlbinlog --start-position=1993 --stop-position=2467 /mydata/data/mysql-bin.000004 > /tmp/recovery.sql
# 設置sql_log_bin=0,不記錄恢復的二進制日誌,滾動一下日誌;
mysql> SET sql_log_bin=0;
mysql> FLUSH LOGS;
# 導入備份文件,完全備份---> 增量備份---->最近的二進制日誌:
[root@localhost ~]#mysql -uroot -p < /backup/alldb_full-2013-09-07.sql
Enter password:
[root@localhost ~]#mysql -uroot -p < /backup/alldb_incre_2013-09-07.sql
Enter password:
[root@localhost ~]#mysql -uroot -p < /tmp/recovery.sql
Enter password:
最後SHOWDATABASES;查看恢復情況
恢復完成後,滾動一下日誌,並開啓二進制日誌
# FLUSHLOGS;
# mysql> SET sql_log_bin=1;
二、LVM快照卷備份:
1、準備工作,創建LVM用以存儲數據庫數據,編譯安裝時指定datadir爲/mydata/data
[root@localhost ~]#pvcreate /dev/sda3
Physical volume "/dev/sda3"successfully created
[root@localhost ~]#pvcreate /dev/sda5
Physical volume "/dev/sda5"successfully created
[root@localhost ~]#vgcreate myvg /dev/sda{3,5}
Volume group "myvg" successfullycreated
[root@localhost ~]#lvcreate -L 10G -n mylv -p rw myvg
Logical volume "mylv" created
[root@localhost ~]# lvs
LV VG Attr LSize Pool Origin Data% Move LogCpy%Sync Convert
mylv myvg -wi-a---- 10.00g
root vg0 -wi-ao--- 20.00g
swap vg0 -wi-ao--- 2.00g
usr vg0 -wi-ao--- 10.00g
var vg0 -wi-ao--- 20.00g
[root@localhost ~]#mke2fs -t ext4 -L MYDATA /dev/myvg/mylv
mke2fs 1.41.12(17-May-2010)
Filesystem label=MYDATA
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096(log=2)
Stride=0 blocks, Stripewidth=0 blocks
655360 inodes, 2621440blocks
131072 blocks (5.00%)reserved for the super user
First data block=0
Maximum filesystemblocks=2684354560
80 block groups
32768 blocks per group,32768 fragments per group
8192 inodes per group
Superblock backupsstored on blocks:
32768, 98304, 163840, 229376, 294912,819200, 884736, 1605632
Writing inode tables:done
Creating journal (32768blocks): done
Writing superblocks andfilesystem accounting information: done
This filesystem will beautomatically checked every 22 mounts or
180 days, whichevercomes first. Use tune2fs -c or -i tooverride.
[root@localhost ~]#mkdir /mydata/data -pv
mkdir: createddirectory `/mydata'
mkdir: createddirectory `/mydata/data'
[root@localhost ~]#mount /dev/myvg/mylv /mydata/data/
[root@localhost ~]# ls/mydata/data/
lost+found
使用Innodb引擎時,建議將每個數據庫的文件單獨存在,不要將所有數據存在一個表空間內,可以調整參數
innodb_file_per_table=1,將此參數保存在/etc/my.cnf裏面的[mysqld]下面;
使用LVM snapshot備份的前提:事務日誌必須跟數據文件在同一個LV上;
開始備份:
請求讀鎖,並滾動日誌;
mysql> FLUSH TABLESWITH READ LOCK;
mysql> FLUSH LOGS;
記錄當前狀態
mysql> SHOW MASTERSTATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB |Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000006| 107 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
爲數據所在的卷創建快照:
[root@localhost data]#lvcreate -L 200M -n mysql-snap -s -p r /dev/myvg/mylv
掛載快照卷,並將快照捲上的數據拷出;
[root@localhost data]#mount /dev/myvg/mysql-snap /mnt
mount: block device/dev/mapper/myvg-mysql--snap is write-protected, mounting read-only
[root@localhost data]#mkdir /backup
[root@localhost ~]# cp-Rp /mnt/* /backup/
拷貝完成之後,卸載並刪除快照卷
[root@localhost ~]#umount /mnt
[root@localhost ~]#lvremove /dev/myvg/my
解除讀鎖
mysql> UNLOCK TABLES;
數據庫又進行了一些操作,此時進行增量備份;
[root@localhost ~]#mysqlbinlog --start-position=107 /mydata/data/mysql-bin.000006 > /tmp/mysql\ >-snap.incremental1.sql;
過了一段時間後,模擬數據庫出現故障:
[root@localhost ~]#service mysqld stop
Shutting downMySQL....[ OK ]
[root@localhost ~]# rm-rf /mydata/*
[root@localhost ~]# cp-pR /backup/* /mydata/
[root@localhost ~]#service mysqld start
Starting MySQL[ OK ]
查看數據庫中的數據,只是完全備份後的狀態,此時再將二進制文件導入,即可恢復上次增量備份時的數據,如果像剛纔一樣把數據庫的所有內容,包括二進制日誌都刪除,那麼也只能恢復到上次增量備份時;所以二進制日誌對數據恢復非常重要,一定要妥善管理;
# mysql -uroot -p < /tmp/mysql-snap.incremental1.sql
數據恢復完成。
Xtrabackup 簡介
Xtrabackup是由percona提供的mysql數據庫備份工具,據官方介紹,這也是世界上惟一一款開源的能夠對innodb和xtradb數據庫進行熱備的工具。特點:
(1)備份過程快速、可靠;
(2)備份過程不會打斷正在執行的事務;
(3)能夠基於壓縮等功能節約磁盤空間和流量;
(4)自動實現備份檢驗;
(5)還原速度快;
獲取軟件:http://www.percona.com/software/percona-xtrabackup/
Xtrabackup備份基於LSN (日誌序列號),在備份時,既包含事務日誌,有包含數據文件,由於是熱備,有的事務還沒有提交,數據還沒有完全同步到磁盤上,xtrabackup恢復數據之前會做預處理,把事務日誌中已提交的事務同步至數據文件,未提交事務要rollback,但是在恢復時,先不要回滾。
軟件安裝
# yum localinstall percona-xtrabackup-2.1.4-656.rhel6.x86_64.rpm
開始備份
1、完全備份:
# mkdir/backup/fullbackup -pv
# innobackupex --no-timestamp /backup/fullback-`date +%F`
--no-timestamp表示不使用自動生成的以日期爲目錄名的目錄
最後出現complete OK!表示成功;
innobackupex: Backupcreated in directory '/backup/fullback-2013-09-09'
innobackupex: MySQLbinlog position: filename 'mysql-bin.000001', position 107
130909 01:51:36 innobackupex: Connection to database serverclosed
130909 01:51:36 innobackupex: completed OK!
2、恢復數據前的準備:
“準備”的主要作用正是通過回滾未提交的事務及同步已經提交的事務至數據文件也使得數據文件處於一致性狀態。
# innobackupex--apply-log /backup/fullback-2013-09-09/
130909 01:34:55 innobackupex: completed OK!
3、從一個完全備份中恢復:
首先模擬數據庫損壞
# servicemysqld stop
# rm -rf/mydata/data/*
# innobackupex--copy-back /backup/fullback-2013-09-09/
130909 01:54:28 innobackupex: completed OK!
恢復完成後啓動數據庫,注意:修改此時數據目錄的權限:
# chown -R mysql.mysql/mydata/data/
# service mysqld start
完全備份並恢復完成!
Xtrabackup在進行增量備份和恢復時,其思路不同於其他備份工具
在每一次完全備份恢復之後,立即再做一次完全備份;
# innobackupex--no-timestamp /backup/fullback-`date +%F`
修改數據庫內容後,進行增量備份,使用--incremental選項,同時增量備份針對的對象要指明;
# innobackupex --incremental --no-timestamp /backup/first.incremental-`date +%F`--incremental-basedir=/backup/fullback-2013-09-09/
innobackupex: Backupcreated in directory '/backup/first.incremental-2013-09-09'
innobackupex: MySQLbinlog position: filename 'mysql-bin.000001', position 391
130909 02:08:02 innobackupex: Connection to database serverclosed
130909 02:08:02 innobackupex: completed OK!
第二次增量備份:
# innobackupex--incremental --no-timestamp /backup/second.incremental-`date +%F`--incremental-basedir=/backup/first.incremental-2013-09-09/
innobackupex: Backupcreated in directory '/backup/second.incremental-2013-09-09'
innobackupex: MySQLbinlog position: filename 'mysql-bin.000001', position 848
130909 02:13:06 innobackupex: Connection to database serverclosed
130909 02:13:06 innobackupex: completed OK!
隨後又進行了一些操作後,數據庫發生故障,那麼下一步開始恢復數據庫
1、準備完全備份:
# innobackupex--apply-log --redo-only /backup/fullback-2013-09-09/
xtrabackup: startingshutdown with innodb_fast_shutdown = 1
130909 2:19:57 InnoDB: Starting shutdown...
130909 2:19:57 InnoDB: Shutdown completed; log sequence number 1621004
130909 02:19:57 innobackupex: completed OK!
2、準備第一個增量備份:
# innobackupex--apply-log --redo-only /backup/fullback-2013-09-09/--incremental-dir=/backup/first.incremental-2013-09-09/
innobackupex: Copying'/backup/first.incremental-2013-09-09/performance_schema/events_waits_summary_global_by_event_name.frm'to'/backup/fullback-2013-09-09/performance_schema/events_waits_summary_global_by_event_name.frm'
130909 02:22:25 innobackupex: completed OK!
3、準備第二個增量備份:
# innobackupex--apply-log --redo-only /backup/fullback-2013-09-09/--incremental-dir=/backup/second.incremental-2013-09-09/
innobackupex: Copying'/backup/second.incremental-2013-09-09/performance_schema/events_waits_summary_global_by_event_name.frm'to'/backup/fullback-2013-09-09/performance_schema/events_waits_summary_global_by_event_name.frm'
130909 02:23:33 innobackupex: completed OK!
4、恢復完全備份,此時的完全備份文件已經將後面的兩次增量進行了“prepared”,所以只恢復完全備份即可
# innobackupex--copy-back /backup/fullback-2013-09-09/
innobackupex: Startingto copy InnoDB log files
innobackupex: in'/backup/fullback-2013-09-09'
innobackupex: back tooriginal InnoDB log directory '/mydata/data'
innobackupex: Finishedcopying back files.
130909 02:27:30 innobackupex: completed OK!
5、數據文件權限:
# chown-R mysql.mysql /mydata/data/*
6、最後利用二進制日誌恢復最後的內容:
找到備份文件中最後的二進制日誌位置
# cat/backup/fullback-2013-09-09/xtrabackup_binlog_info
mysql-bin.000001 848
# mysqlbinlog--start-position=848 /backup/mysql-bin.000001 > last.sql
先把二進制日誌關掉,然後再把日誌導入,隨後再開啓日誌;
# SET SESSION SQL_LOG_BIN=0;
# mysql < last.sql
# SET SESSION SQL_LOG_BIN=1;
增量備份恢復最終完成,