關於mysql備份和還原的介紹、類型、方法官網很詳細,傳送門:https://dev.mysql.com/doc/mysql-backup-excerpt/8.0/en/backup-and-recovery.htmlhtml
下面介紹MySQL備份的幾種經常使用方法與恢復步驟mysql
在平常工做中,咱們會使用mysqldump命令建立sql格式的轉儲文件來備份數據庫。或者咱們把數據導出後作數據遷移,主備搭建等操做。mysqldump是一個邏輯備份工具,複製原始的數據庫對象定義和表數據產生一組可執行的SQL語句。 默認狀況下,生成insert語句,也能生成其它分隔符的輸出或XML格式的文件。ios
shell> mysqldump [arguments] > file_namesql
咱們簡單的來看一下平常的用法:shell
備份全部的數據庫:數據庫
shell> mysqldump --all-databases > dump.sql (不包含INFORMATION_SCHEMA,performance_schema,sys,若是想要導出的話還要結合--skip-lock-tables和--database一塊兒用)服務器
備份指定的數據庫:session
shell> mysqldump --databases db1 db2 db3 > dump.sqloracle
當咱們只備份一個數據的時候能夠省去 --databases 直接寫成:mysqldump test > dump.sql 不過有一些細微的差異,若是不加的話,數據庫轉儲輸出不包含建立數據庫和use語句,因此能夠不加這個參數直接導入到其它名字的數據庫裏app
固然咱們也能夠只備份某個表 :
mysqldump --user [username] --password=[password] [database name] [table name] table_name.sql
瞭解了簡單的一些用法後咱們再着重的看一下幾個參數:
--master-data 獲取備份數據的Binlog位置和Binlog文件名,用於經過備份恢復的實例之間創建複製關係時使用,該參數會默認開啓。
--dump-slave 用於在slave上dump數據,創建新的slave。由於咱們在使用mysqldump時會鎖表,因此大多數狀況下,咱們的導出操做通常會在只讀備庫上作,爲了獲取主庫的Relay_Master_Log_File和Exec_Master_Log_Pos,須要用到這個參數,不過這個參數只有在5.7之後的纔會有
–no-data, -d 不導出任何數據,只導出數據庫表結構
剛剛咱們說過在使用mysqldump的時候會鎖表,咱們來詳細的看一下它的鎖機制。
咱們開兩個窗口,在第一個裏面執行mysqldump -uroot -pxxxxx --master-data=2 --databases dbname > /tmp/dbname date +%F .sql
而後第二個窗口登錄進去,使用show process的命令能夠看到目前dump的session正在執行
SELECT /*!40001 SQL_NO_CACHE */ * FROM table_name; 能夠看到這條sql正在以no_cache的模式查詢數據。
而後咱們在一樣的表上執行一下select,發現被阻塞了。光標一直不返回。
通常遇到這種文件,咱們會想是否是有鎖呢?
爲了驗證咱們查看一下鎖的信息,能夠發現dump的進程其實是加了鎖的。
咱們把具體的general_log打開,而後看一下當時的操做:
4101044 Query FLUSH /*!40101 LOCAL */ TABLES
4101044 Query FLUSH TABLES WITH READ LOCK (關閉全部打開的表,同時對於全部數據庫中的表都加一個讀鎖,直到顯示地執行unlock tables,該操做經常用於數據備份的時候。)
4101044 Query SHOW MASTER STATUS(這是由於我用了--master-data=2)
因此這個時候表就會被鎖住。
若是我不加--master-data參數(mysqldump -uroot -pxx --databases db > /tmp/dbname date +%F .sql) mysql會顯示的對每一張要備份的表執行
LOCK TABLES table_name1 READ,LOCK TABLES table_name2 READ
而且也不會有讀的阻塞。
那有沒有不鎖的方法?
其實也是有的,就是使用--single-transaction把備份的操做放在一個事務裏去進行
帶上--single-transaction參數的mysqldump備份過程:
若是是5.6版本的mysql
在備份之間一樣的先FLUSH TABLES WITH READ LOCK,而後設置事務級別SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ,而後開啓一個事務START TRANSACTION進行備份,這個時候備份的過程就很意思,它先建立了一個savepoint,而後把數據庫裏的表依次的進行備份,備份完成了以後又回滾到了以前的savepoint,來保證數據的一致性
若是是5.7版本的mysql
備份前的操做相同,只是沒有了savepoint
不過不論是哪一個版本,只有InnoDB表是在一個一致性的狀態。其它的任何MyISAM表或內存表是沒有用的。
mysqldump的優點是能夠查看或者編輯十分方便,它也能夠靈活性的恢復以前的數據。它也不關心底層的存儲引擎,既適用於支持事務的,也適用於不支持事務的表。不過它不能做爲一個快速備份大量的數據或可伸縮的解決方案。若是數據庫過大,即便備份步驟須要的時間不算過久,但有可能恢復數據的速度也會很是慢,由於它涉及的SQL語句插入磁盤I/O,建立索引等等。
對於大規模的備份和恢復,更合適的作法是物理備份,複製其原始格式的數據文件,能夠快速恢復:若是你的表主要是InnoDB表,或者若是你有一個InnoDB和MyISAM表,能夠考慮使用MySQL的mysqlbackup命令備份
恢復操做:
先看一下當前的數據:
dbadmin@test 11:10:34>select * from t;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
備份;
mysqldump -uroot -proot@1234 --master-data=1 test >test.sql
模擬增量操做:
dbadmin@test 11:15:17>insert into t values (2);
Query OK, 1 row affected (0.00 sec)
dbadmin@test 11:15:36>select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.00 sec)
模擬誤操做:
dbadmin@test 11:15:41>truncate table t;
Query OK, 0 rows affected (0.01 sec)
dbadmin@test 11:16:14>select * from t;
Empty set (0.00 sec)
摸擬恢復操做:
step 1:找到誤操做的log position
dbadmin@test 11:20:57>show master logs;
dbadmin@(none) 11:21:37>show binlog events in 'mysql-bin.000004';
查看能夠看到是444
step 2:
恢復到備份
dbadmin@test 11:16:25>source test.sql
dbadmin@test 11:17:26>select * from t;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
step 3:
由於咱們在備份的時候使用了master-data的參數,因此能夠直接看到備份時候的最後位置,而後應用中間的log。
查看能夠看到是187
咱們使用mysqlbinlog獲得這一段時間的操做,其實咱們也能夠用這個工具獲得操做後使用sed進行undo的操做。
mysqlbinlog --start-position=187 --stop-position=444 mysql-bin.000004 > increment.sql
dbadmin@test 11:44:37>source /u01/my3307/log/increment.sql
dbadmin@test 11:44:50>select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
至此數據恢復。
是ORACLE公司提供的針對企業的備份軟件,全名叫作MySQL Enterprise Backup,是一個收費的軟件。 下載地址:
https://www.mysql.com/products/enterprise/backup.html 能夠試用下載。
咱們簡單的來看一下這個工具的使用。
查看全部的幫助:
我這裏只是截取了一小部分,這個幫助很長,參數不少,功能很全,是oracle官方主推的備份方式。
全量備份:
mysqlbackup --user=root --password=ucjmh --databases='t1' --encrypt-password=1 --with-timestamp --backup-dir=/u01/backup/ backup
解釋一下參數:
--databases 要備份的數據庫
--with-timestamp 產生一個當前時間的備份目錄。mysqlbackup這個工具要求一個空目錄才能作備份。因此這個會經常使用
--backup-dir 備份的目錄
--compress:壓縮備份 這個提供了多種壓縮方法和壓縮級別。1--9,壓縮比依次遞增
backup 是備份的方式, 一共有以下幾種方式,我會在一個恢復案例裏把經常使用的幾個都用到
Backup operations: backup, backup-and-apply-log, backup-to-image
Update operations: apply-log, apply-incremental-backup
Restore operations: copy-back, copy-back-and-apply-log
Validation operation: validate
Single-file backup operations: image-to-backup-dir, backup-dir-to-image, list-image, extract
其實,在大多數狀況下,單個文件備份,使用backup-to-image命令建立,性能優於backup。buckup這個命令只執行一個完整的備份過程的初始階段。須要經過再次運行mysqlbackup運用apply-log 命令,使備份一致。
mysqlbackup --user=root --password=ucjmh --databases='t1' --encrypt-password=1 --with-timestamp --backup-dir=/u01/backup/2017-04-28_12-49-35/ apply-log
固然你能夠直接用backup-and-apply-log 不過這個時候的備份將不能用於增量了。
增量備份:
mysqlbackup --user=root --password=ucjmh --databases='t1' --encrypt-password=1 --with-timestamp --backup-dir=/u01/backup/ --incremental --incremental-base=dir:/u01/backup/2017-04-28_12-49-35 --incremental-backup-dir=/u01/backup/incremental backup
這個是基於上次的備份作的備份,固然也能夠基於某一個log position以後作。
--incremental:表明增量備份;
--incremental-base:上次全備的目錄;
--incremental-backup-dir:增量備份的保存的目錄
再多說一點關於image的備份:
使用以下命令能夠進行備份
mysqlbackup --user=root --password=ucjmh --databases='t1' --encrypt-password=1 --with-timestamp --backup-dir=/u01/backup/ --backup-image=all.mbi backup-to-image
備份以後能夠很清楚的發現這個比backup要節省不少空間,把全部的文件都以二進制的方式放在了all.mbi這個文件裏,可使用list-image來查看具體內容。
mysqlbackup --backup-image=/u01/backup/2017-04-28_14-50-17/all.mbi list-image
一樣的也可使用
mysqlbackup --backup-image=/u01/backup/2017-04-28_14-50-17/all.mbi extract
來解壓出來具體的內容。
由於這是一個oracle出的工具,有很深的rman的影子在,0級,1級備份,加密,異構機器還原等特性。
更多的參數能夠參看online help:
https://dev.mysql.com/doc/mysql-enterprise-backup/4.1/en/backup-commands-single-file.html
恢復操做:
查看當前數據
dbadmin@test 11:51:32>select * from t;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.01 sec)
全量備份
mysqlbackup --user=root --password=root@1234 --databases='test' --with-timestamp --backup-dir=/data/backup/ backup
模擬增量操做:
dbadmin@test 11:54:04>select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.00 sec)
增量備份:
mysqlbackup --user=root --password=root@1234 --databases='test' --with-timestamp --backup-dir=/data/backup/ --incremental --incremental-base=dir:/data/backup/2017-04-29_11-53-20 --incremental-backup-dir=/data/backup/incremental backup
模擬無備份操做:
dbadmin@test 11:57:10>select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
模擬誤操做:
dbadmin@test 11:57:17>truncate table t;
Query OK, 0 rows affected (0.01 sec)
摸擬恢復操做:
step 1:找到誤操做的log position
dbadmin@test 11:58:06>show master logs;
dbadmin@test 11:58:18>show binlog events in 'mysql-bin.000001';
1333
step 2:恢復全量
檢測並應用日誌:
mysqlbackup --backup-dir=/data/backup/2017-04-29_11-53-20 apply-log
step 3:應用增量
mysqlbackup --backup-dir=/data/backup/2017-04-29_11-53-20 --incremental-backup-dir=/data/backup/incremental/2017-04-29_11-55-54 apply-incremental-backup
step 4:物理文件複製還原
mysqlbackup --backup-dir=/data/backup/2017-04-29_11-53-20 copy-back
數據恢復到備份的時候:
dbadmin@test 12:09:49>select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.00 sec)
恢復完成以後,data目錄下會生成backup_variables.txt的文件(其實在備份的時候就已經有這些文件的),找到備份的時候的log position,而後從binlog恢復無備份的數據
binlog_position=mysql-bin.000001:1076
mysqlbinlog mysql-bin.000001 --start-position=1076 --stop-position=1333 -vv >increment.sql
dbadmin@test 12:14:07>source /u01/my3307/log/increment.sql
dbadmin@test 12:14:16>select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
至此數據恢復。
大體梳理一下操做步驟,來了解一下恢復的原理:
首先檢測並應用全備事務日誌文件(這裏是由於我備份的時候用的是backup而不是backup-and-apply-log),而後基於全備去應用增量的log。這個時候若是有屢次增量備份也能夠(基於LSN點向後應用)。 全部的都應用完成以後就是一個能夠直接cp的數據庫了。
我的感受這個工具比xtrabackup好用,可是xtrabackup是開源的,因此市場佔有量纔會大,纔會更有名,更多人用吧。
mysqlhotcopy使用lock tables、flush tables和cp或scp來快速備份數據庫.它是備份數據庫或單個表最快的途徑,徹底屬於物理備份,但只能用於備份MyISAM存儲引擎和ARCHIVE引擎,而且是一個服務器命令,只能運行在數據庫目錄所在的機器上.與mysqldump備份不一樣,mysqldump屬於邏輯備份,備份時是執行的sql語句.使用mysqlhotcopy命令前須要要安裝相應的軟件依賴包.
由於這個功能很弱,咱們只簡單的介紹一個怎麼用:
備份一個庫
mysqlhotcopy db_name [/path/to/new_directory]
備份一張表
mysqlhotcopy db_name./table_name/ /path/to/new_directory
更詳細的使用可使用perldoc mysqlhotcopy查看
Percona XtraBackup是一款基於MySQL的熱備份的開源實用程序,它能夠備份5.1到5.7版本上InnoDB,XtraDB,MyISAM存儲引擎的表。
Xtrabackup有兩個主要的工具:xtrabackup、innobackupex
(1)xtrabackup只能備份InnoDB和XtraDB兩種數據表,而不能備份MyISAM數據表
(2)innobackupex則封裝了xtrabackup,是一個腳本封裝,因此能同時備份處理innodb和myisam,但在處理myisam時須要加一個讀鎖
首先咱們先來簡單的瞭解一下xtrabackup是怎麼工做的。xtrabackup基於innodb的crash-recovery(實例恢復)功能,先copy innodb的物理文件(這個時候數據的一致性是沒法知足的),而後進行基於redo log進行恢復,達到數據的一致性。詳細的信息能夠參數https://www.percona.com/doc/percona-xtrabackup/LATEST/how_xtrabackup_works.html 我就不翻譯了。
咱們仍是簡單的來看一下平常工做中具體的使用:
全量備份:
xtrabackup --backup --target-dir=/data/backup/base
能夠先看到:
在備份過程當中,能夠看到不少輸出顯示數據文件被複制,以及日誌文件線程反覆掃描日誌文件和複製。
一樣的它也輸出了當前的binlog filename和position,若是有gtid(一樣也會輸出) 能夠用於搭建主從。最後一行必定會是你的lsn被copy的信息。
這是由於每次啓動備份,都會記錄170429 12:54:10 >> log scanned up to (1676085)),而後開始拷貝文件,通常來說數據庫越大拷貝文件是要花費越長的時間,因此說這期間通常狀況都會有新的操做,因此說全部文件也可能記錄的並非一個時間點的數據。
爲了解決數據這個問題,XtraBackup 就會啓動一個後臺進程來每秒1次的觀測mysql的事務日誌,直到備份結束。並且把事務日誌中的改變記錄下來。咱們知道事物日誌是會重用的(redo log),因此這個進程會把redolog寫到本身的日誌文件xtrabackup_log,這個後臺監控進程會記錄全部的事務日誌的改變,用於保證數據一致性所。
增量備份:
當咱們作過全量備份之後會在目錄下產生xtrabackup_checkpoints的文件 這裏面記錄了lsn和備份方式,咱們能夠基於此次的全量作增量的備份。
$cat xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 1676085
last_lsn = 1676085
compact = 0
recover_binlog_info = 0
xtrabackup --backup --target-dir=/data/backup/inc1 --incremental-basedir=/data/backup/base
這個時候xtrabackup也是去打開了xtrabackup_checkpoints文件進行上一次備份的信息查看。這個時候去查看增量備份的xtrabackup_checkpoints也記錄了這些信息
$cat xtrabackup_checkpoints
backup_type = incremental
from_lsn = 1676085
to_lsn = 1676085
last_lsn = 1676085
compact = 0
recover_binlog_info = 0
這也意味着你能夠在增量的備份上繼續增量的備份。
一樣的xtrabackup也支持壓縮(--compress)、加密(--encrypt)、並行(--parallel)等操做,可是和mysqlbackup不一樣的是這個沒有同時的備份binlog,而mysqlbackup是備份了binlog的。
咱們來模擬一個恢復的過程深刻的瞭解一下原理——
查看當前數據:
dbadmin@test 03:04:33>select * from t;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
全量備份
$xtrabackup --backup --target-dir=/data/backup/base
模擬增量數據
dbadmin@test 03:07:16>select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.00 sec)
進行增量備份:
$xtrabackup --backup --target-dir=/data/backup/inc1 --incremental-basedir=/data/backup/base
模擬無備份操做:
dbadmin@test 03:09:42>select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
模擬誤操做:
dbadmin@test 03:09:45>truncate table t;
Query OK, 0 rows affected (0.00 sec)
摸擬恢復操做:
找到誤操做的log position
dbadmin@test 03:10:19>show master logs;
dbadmin@test 03:10:47>show binlog events in 'mysql-bin.000001';
1333
咱們須要分別對全量、增量備份各作一次prepare操做。
xtrabackup --prepare --apply-log-only --target-dir=/data/backup/base
增量
xtrabackup --prepare --apply-log-only --target-dir=/data/backup/base \
--incremental-dir=/data/backup/inc1
若是咱們使用它自帶的還原命令的時候就要先把data目錄給清空。否則就會報以下的錯誤
$innobackupex --copy-back /data/backup/base/
170429 15:37:19 innobackupex: Starting the copy-back operation
IMPORTANT: Please check that the copy-back run completes successfully.
At the end of a successful copy-back run innobackupex
prints "completed OK!".
innobackupex version 2.4.6 based on MySQL server 5.7.13 Linux (x86_64) (revision id: 8ec05b7)
Original data directory /u01/my3307/data is not empty!
固然咱們大多數據時候是不會在原來的實例上作操做的,都會把相應的備份在奇他的實例上進行恢復,而後再導出導入到誤操做的實例。這裏咱們直接清掉目錄,而後再次運行,查看恢復後的數據:
dbadmin@test 03:41:56>select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.00 sec)
一樣的被恢復的目錄裏會多出來兩個文件,一個是xtrabackup_binlog_pos_innodb,一個是xtrabackup_info。在這兩個文件中均可以看到你最後的log,pos。在info裏還能夠看到lsn。咱們基於這個pos再進行binlog的重演,恢復在binlog沒有被備份的數據。
1076
$mysqlbinlog mysql-bin.000001 --start-position=1076 --stop-position=1333 -vv >increment.sql
dbadmin@test 03:51:25>source /u01/my3307/log/increment.sql
dbadmin@test 03:51:34>select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
至此數據恢復完成
https://www.percona.com/doc/percona-xtrabackup/LATEST/backup_scenarios/full_backup.html
MySQL有一種很是簡單的備份方法,就是將MySQL中的數據庫文件直接複製出來。這是最簡單,速度最快的方法。
不過在此以前,要先將服務器中止,這樣才能夠保證在複製期間數據庫的數據不會發生變化。若是在複製數據庫的過程當中還有數據寫入,就會形成數據不一致。這種狀況在開發環境能夠,可是在生產環境中很難容許備份服務器。
注意:這種方法不適用於InnoDB存儲引擎的表,而對於MyISAM存儲引擎的表很方便。同時,還原時MySQL的版本最好相同。
之因此提這一點是由於當有停機窗口時,搭建主從的時候,這個每每是最快的。
-------------------
通常生產環境的備份都會用percona-xtrabackup或者mysqlbackup,結合本身的狀況,選擇合適的備份策略,適時拿出來驗證備份的有效性。