1. 程式人生 > >Mysql/Mariadb備份(xtrabackup)還原實戰

Mysql/Mariadb備份(xtrabackup)還原實戰

mysql二進制日誌 mysqdump備份 xtrabackup備份 mysql完整備份 mysql增量備份與恢復

一、概述

之前的文章說到mysql的安裝與mysql的基本使用;本文是後續補充,主要說明針對mysql或mariadb的備份與還原;眾所周知,數據是重中之重,因此平時對企業數據需要做備份,當數據系統崩潰,數據丟失異常時,才能依據備份文件進行恢復!
本次的環境:
CentOS7.4_x64 , mysql5.7.21, xtrabackup
mysql的安裝配置可參考之前系列文章;只補充相關配置項的開啟;以及xtrabackup安裝使用;
用到的演示數據導入mysql數據庫

[root@db ~]# mysql -uroot -predhat < testdb.sql
或
mysql> source   testdb.sql
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| example            |
| mysql              |
| performance_schema |
| study              |
| sys                |
以上study即為測試數據庫包含以下測試表

mysql> show tables;
+-----------------+
| Tables_in_study |
+-----------------+
| class           |
| course          |
| part            |
| score           |
| student         |
| tb31            |
| tb32            |
| teacher         |
| test1           |
| test2           |
| user_info       |
+-----------------+

測試數據庫及數據表準備完成,在進行數據的備份與恢復前,我們先簡單了解下數據庫備份與恢復的相關概念原理;

關於數據庫的備份與還原
為什麽備份?
主要是為了災難恢復如:硬件故障(冗余)、軟件故障(bug)、自然災害、黑客攻擊、誤操作、以及測試需要導出數據等;
還原或叫恢復時即基於以往的備份文件;
備份類型
全量備份、增量備份、差異備份:
完全備份: 備份數據的副本(某時間點);
增量備份:僅備份自上一次完全備份或 增量備份以來變量的那部數據;
差異備份:僅備份自上一次完全備份以來變量的那部數據;

物理備份、邏輯備份:
物理備份:復制數據文件進行的備份;
邏輯備份:從數據庫導出數據另存在一個或多個文件中;

根據數據服務是否在線:

熱備:讀寫操作均可進行的狀態下所做的備份;
溫備:可讀但不可寫狀態下進行的備份;
冷備:讀寫操作均不可進行的狀態下所做的備份
以上的各備份類型備份執行時只能備份數據在備份時的狀態,如想要恢復數據庫崩潰那一刻的狀態,需要打開binary log功能,需要基於備份的數據+binary log來恢復到數據崩潰前一刻的狀態;
備份的工具有mysqldump(溫備,不適合大型數據的在線備份),xtrabackup(支持對InnoDB熱備,開源專業的備份數據,支持mysql/mariadb)本文將通過mysqldump與xtrabackup來說明數據的備份與恢復(異地);

無論那種工具備份,在恢復時均要binary log才能恢復到崩潰前的狀態;因此需要配置數據庫開啟binary log功能;以下能mysql5.7.21

#cat /usr/local/mysql/etc/my.cnf
server-id       = 1
log_bin         = /data1/mysqldb/mysql-bin.log

二、mysqldump備份與恢復

mysqldump使用說明
單進程邏輯備份、完全備份、部分備份;

Usage: 
mysqldump [OPTIONS] database [tables]
         OR     mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]
         OR     mysqldump [OPTIONS] --all-databases [OPTIONS]

mysqldump mydb:表級別備份(還原時庫需要存在)
mysqldump --databases mydb:庫級別備份(庫不在會自行創建庫)

MyISAM存儲引擎:支持溫備,備份時要鎖定表;
         -x, --lock-all-tables:鎖定所有庫的所有表,讀鎖;
         -l, --lock-tables:鎖定指定庫所有表;

InnoDB存儲引擎:支持溫備和熱備;
         -x, --lock-all-tables:鎖定所有庫的所有表,讀鎖;
         -l, --lock-tables:鎖定指定庫所有表;
        --single-transaction:創建一個事務,基於此快照執行備份;
                -R, --routines:存儲過程和存儲函數;
                --triggers      觸發器
                -E, --events      事件

                 --master-data[=#]
                        1:記錄為CHANGE MASTER TO語句,此語句不被註釋;
                        2:記錄為CHANGE MASTER TO語句,此語句被註釋;

                --flush-logs:鎖定表完成後,即進行日誌刷新操作(重新生成binlog日誌);

基於mysqldump備份study數據庫

熱備,備份存儲過程和存儲函數,事件,並記得下事件位置;(便於從binlog中的位置開始恢復到故障前)
#mysqldump -uroot -predhat --single-transaction  -R -E --triggers --master-data=2 --databases study >/home/san/studydb.sql

說明:
less studydb.sql
會看到以下內容

-- CHANGE MASTER TO MASTER_LOG_FILE=‘mysql-bin.000005‘, MASTER_LOG_POS=154;

這就是--master-data=2 選項作用,註釋了,binary log 點在154
模擬備份後數據修改操作

修改前的:
mysql> select * from user_info;
+-----+-------+------+--------+----------+
| nid | name  | age  | gender | part_nid |
+-----+-------+------+--------+----------+
|   1 | san   |   20 | 男     |        1 |
|   2 | dong  |   29 | 男     |        2 |
|   4 | Ling  |   28 | 男     |        4 |
|   5 | ling  |   28 | 男     |        3 |
|   6 | dong  |   30 | 男     |        1 |
|   7 | b     |   11 | 女     |        1 |
|   8 | c     |   12 | 女     |        1 |
|   9 | d     |   18 | 女     |        4 |
|  10 | e     |   22 | 男     |        3 |
|  11 | f     |   23 | 男     |        2 |
|  12 | dongy |   22 | 男     |        1 |
+-----+-------+------+--------+----------+
11 rows in set (0.00 sec)
增加一條:
mysql> insert into user_info values(13,‘hi‘,18,‘男‘,4);
Query OK, 1 row affected (0.03 sec)
刪除一條:
mysql> delete  from user_info where nid=1;
Query OK, 1 row affected (0.01 sec)
最終在上次備份後user_info數據如下:
mysql> select * from user_info;
+-----+-------+------+--------+----------+
| nid | name  | age  | gender | part_nid |
+-----+-------+------+--------+----------+
|   2 | dong  |   29 | 男     |        2 |
|   4 | Ling  |   28 | 男     |        4 |
|   5 | ling  |   28 | 男     |        3 |
|   6 | dong  |   30 | 男     |        1 |
|   7 | b     |   11 | 女     |        1 |
|   8 | c     |   12 | 女     |        1 |
|   9 | d     |   18 | 女     |        4 |
|  10 | e     |   22 | 男     |        3 |
|  11 | f     |   23 | 男     |        2 |
|  12 | dongy |   22 | 男     |        1 |
|  13 | hi    |   18 | 男     |        4 |
+-----+-------+------+--------+----------+
11 rows in set (0.00 sec)
可以看出少了一條,加了一條;

模擬數據庫損壞並恢復study數據庫
關閉mysql並到數據目錄刪除study數據庫;

假設發現study數據已經丟失了;
數據庫運行正常;查看binlog位置
mysql> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       815 |
| mysql-bin.000002 |       177 |
| mysql-bin.000003 |       177 |
| mysql-bin.000004 |   1890875 |
| mysql-bin.000005 |       725 |
+------------------+-----------+
記住這裏最後一個binlog文件及位置是mysql-bin.000005   725
結合上面備份文件中的-- CHANGE MASTER TO MASTER_LOG_FILE=‘mysql-bin.000005‘, MASTER_LOG_POS=154; 可以分析出備份時位置是154而數據庫丟失前是725
因此我們恢復study數據庫裏需要恢復上次的全備+加mysql-bin.000005中的154-725內容;

模擬study丟失過程(傳說潰的刪庫路)
[root@db mysqldb]# service stop mysqld
[root@db mysqldb]# pwd
/data1/mysqldb
[root@db mysqldb]# rm -rf  study/
啟動數據庫
[root@db mysqldb]# service stop mysqld
登錄數據庫並查看發現study數據庫已經丟失了

還原數據庫

mysql -uroot -predhat < studydb.sql
mysql> show databases;
可發現已經恢復;但是之前完整備份的到崩潰前的修改不見了;如下:
mysql> select * from user_info;
+-----+-------+------+--------+----------+
| nid | name  | age  | gender | part_nid |
+-----+-------+------+--------+----------+
|   1 | san   |   20 | 男     |        1 |
|   2 | dong  |   29 | 男     |        2 |
|   4 | Ling  |   28 | 男     |        4 |
|   5 | ling  |   28 | 男     |        3 |
|   6 | dong  |   30 | 男     |        1 |
|   7 | b     |   11 | 女     |        1 |
|   8 | c     |   12 | 女     |        1 |
|   9 | d     |   18 | 女     |        4 |
|  10 | e     |   22 | 男     |        3 |
|  11 | f     |   23 | 男     |        2 |
|  12 | dongy |   22 | 男     |        1 |
+-----+-------+------+--------+----------+
11 rows in set (0.00 sec)

結合binlog恢復:

從binlog上導出sql文件
[root@db mysqldb]# mysqlbinlog mysql-bin.000005 >/root/binlog.sql
登錄mysql恢復
恢復過程中臨時關閉binlog記錄
mysql> set @@session.sql_log_bin=OFF;
mysql> source binlog.sql;
Query OK, 0 rows affected (0.00 sec

mysql> set @@session.sql_log_bin=ON;
mysql> use study; 
mysql> select * from user_info;
+-----+-------+------+--------+----------+
| nid | name  | age  | gender | part_nid |
+-----+-------+------+--------+----------+
|   2 | dong  |   29 | 男     |        2 |
|   4 | Ling  |   28 | 男     |        4 |
|   5 | ling  |   28 | 男     |        3 |
|   6 | dong  |   30 | 男     |        1 |
|   7 | b     |   11 | 女     |        1 |
|   8 | c     |   12 | 女     |        1 |
|   9 | d     |   18 | 女     |        4 |
|  10 | e     |   22 | 男     |        3 |
|  11 | f     |   23 | 男     |        2 |
|  12 | dongy |   22 | 男     |        1 |
|  13 | hi    |   18 | 男     |        4 |
+-----+-------+------+--------+----------+
11 rows in set (0.00 sec)

可以看出study數據庫已經恢復到崩潰損壞前的狀態;另外完全 可以新準備一臺數據庫服務器;把sql轉移到新機器上恢復;前提數據配置參數需要一樣;

三、xtrabackup備份與恢復

xtrabackup簡介
xtrabackup是Percona一款開源工具,支持innodb,Xtradb(mariadb)引擎數據庫的熱備;
對MyISAM:溫備,不支持增量備份;InnoDB:熱備,增量;
物理備份,速率快、可靠;備份完成後自動校驗備份結果集是否可用;還原速度快
功能介紹與Innobackup(mysql企業版收費)對比參考官網
所數據庫引擎請使用innodb引擎

xtrabackup安裝與使用說明

安裝
[官方下載地址](https://www.percona.com/downloads/XtraBackup/LATEST/)
本次使用percona-xtrabackup-24-2.4.8-1
[root@db ~]# wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.8/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.8-1.el7.x86_64.rpm
[root@db ~]# yum install ./percona-xtrabackup-24-2.4.8-1.el7.x86_64.rpm -y

**獲取幫助與使用:**
可以通過man  xtrabackup 獲取詳細使用說明與實例
Usage: 
 innobackupex [--defaults-file=#] --backup | innobackupex [--defaults-file=#] --prepare] [OPTIONS]
 備份用到的主要選項:
    --defaults-file=     #mysql或mariadb配置文件
        --user=                  #備份時使用的用戶(對備份的數據庫有備份權限)
        --password=         #備份用戶密碼
        -H | --host=            #localhost或遠程主機

**恢復時到的主要選項:**
        --apply-log         #分析獲取binary log文件生成backup_binlog_info文件
        ---copy-back      #基於backup_binlog_info等文件恢復
註:innobackupex是xtrabackup的軟件鏈接;

xtrabackup全備與恢復:
註意:備份時數據庫是在線狀態;恢復時需要離線並且mysql數據目錄為空;
備份:

創建備份目錄 
mkdir -pv /data/backup
創建備份授權賬號root(可以是其他用戶最小權限)
mysql> GRANT ALL ON *.* TO ‘root‘@‘127.0.0.1‘ identified by "redhat";
Query OK, 0 rows affected, 1 warning (0.00 sec)

[root@db mysqldb]# innobackupex --defaults-file=/usr/local/mysql/etc/my.cnf --user=root --password=redhat  --host=127.0.0.1 /data/backup
看到類似如下信息表示備份成功:
xtrabackup: Transaction log of lsn (7701576) to (7701585) was copied.
180401 11:52:35 completed OK!
同時在/data/backup目錄中產生以時間為目錄的備份目錄
[root@db backup]# ll /data/backup/
drwxr-x--- 14 root root 4096 4月   1 11:52 2018-04-01_11-52-29

備份後對數據庫study 中的表進行修改

刪除student表
mysql> drop table student;
Query OK, 0 rows affected (0.04 sec)
往user_info表中插入兩行
mysql> insert into user_info values(1,"san",18,"男",4),(14,"Hello",28,"女",2);
Query OK, 1 row affected (0.00 sec)

模擬數據庫崩潰

註意binlog文件備份好;如果binglog和數據目錄在一起
[root@db backup]# service mysqld stop
[root@db backup]# rm -rf /data1/mysqldb/*

恢復數據:

切換到備份數據目錄
[root@db backup]# cd /data/backup/2018-04-01_11-52-29
事務回滾不提交
[root@db 2018-04-01_11-52-29]# innobackupex  --defaults-file=/usr/local/mysql/etc/my.cnf --apply-log ./
類似以下提示表示完成:
InnoDB: Shutdown completed; log sequence number 7702056
180401 12:13:40 completed OK!

數據還原

由於centos7默認有/etc/my.cnf文件
因此需要重命名my.cnf或移除以免影響恢復;
[root@db 2018-04-01_11-52-29]# innobackupex  --defaults-file=/usr/local/mysql/etc/my.cnf --copy-back ./
類似以下提示表示恢復完成:
180401 12:16:15 [01]        ...done
180401 12:16:15 completed OK!

恢復binlog中信息
查看全備中的binlog信息(文件和位置)

[root@db backup]# cat /data/backup/2018-04-01_11-52-29/xtrabackup_binlog_info
mysql-bin.000008        14775
由引可知在上次全備時的binglog文件是mysql-bin.000008位置為14775
獲取binlog信息
[root@db backup]# mysqlbinlog -j 14775 mysql-bin.000008 >/data/backup/binlog.sql
還原binlog中的內容(全備後的修改數據內容)
切換到mysql數據目錄(/data1/mysqldb)並修改權限
[root@db mysqldb]# cd /data1/mysqldb
[root@db mysqldb]# chown mysql.mysql *  -R
啟動mysql
[root@db mysqldb]# service mysqld start

登錄數據庫並導入binlog.sql

mysql> source /data/backup/binlog.sql
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user_info;
+-----+-------+------+--------+----------+
| nid | name  | age  | gender | part_nid |
+-----+-------+------+--------+----------+
|   1 | san   |   18 | 男     |        4 |
|   2 | dong  |   29 | 男     |        2 |
|   4 | Ling  |   28 | 男     |        4 |
|   5 | ling  |   28 | 男     |        3 |
|   6 | dong  |   30 | 男     |        1 |
|   7 | b     |   11 | 女     |        1 |
|   8 | c     |   12 | 女     |        1 |
|   9 | d     |   18 | 女     |        4 |
|  10 | e     |   22 | 男     |        3 |
|  11 | f     |   23 | 男     |        2 |
|  12 | dongy |   22 | 男     |        1 |
|  13 | hi    |   18 | 男     |        4 |
|  14 | Hello |   28 | 女     |        2 |
+-----+-------+------+--------+----------+
13 rows in set (0.00 sec)

xtrabackup 增量備份與恢復
備份流程:
首次增量備份是基於完整備份後做的增量備份 ,後面的增量備份將基於前一次增量備份;
恢復流程:
合並完整備份事務 -->再合並第一次增量的事務-->....最後一次增量備份 +binlog日誌

完整備份:

[root@db ~# innobackupex --defaults-file=/usr/local/mysql/etc/my.cnf --user=root --password=redhat  --host=127.0.0.1 /data/backup
提示類似如下信息完成 :
xtrabackup: Transaction log of lsn (7802468) to (7802477) was copied.
180401 13:13:13 completed OK!
[root@db ~# ll /data/backup
2018-04-01_13-13-10    ######完整備份目錄

模擬數據庫的修改操作

刪除第10行並新增一行
mysql> delete from user_info where nid=10;
Query OK, 1 row affected (0.01 sec)

mysql> insert into user_info value(15,‘hehe‘,22,‘男‘,1);
Query OK, 1 row affected (0.01 sec)

第一次增量備份

[root@db ~# innobackupex --defaults-file=/usr/local/mysql/etc/my.cnf --incremental --user=root --password=redhat  --host=127.0.0.1 /data/backup/ --incremental-basedir=/data/backup/2018-04-01_13-13-10/
提示類似如下信息完成 :
xtrabackup: Transaction log of lsn (7803424) to (7803433) was copied.
180401 13:17:26 completed OK!

再次模擬數據庫的修改操作

mysql> select * from user_info;
+-----+-------+------+--------+----------+
| nid | name  | age  | gender | part_nid |
+-----+-------+------+--------+----------+
|   1 | san   |   18 | 男     |        4 |
|   2 | dong  |   29 | 男     |        2 |
|   4 | Ling  |   28 | 男     |        4 |
|   5 | ling  |   28 | 男     |        3 |
|   6 | dong  |   30 | 男     |        1 |
|   7 | b     |   11 | 女     |        1 |
|   8 | c     |   12 | 女     |        1 |
|   9 | d     |   18 | 女     |        4 |
|  11 | f     |   23 | 男     |        2 |
|  12 | dongy |   22 | 男     |        1 |
|  13 | hi    |   18 | 男     |        4 |
|  14 | Hello |   28 | 女     |        2 |
|  15 | hehe  |   22 | 男     |        1 |
+-----+-------+------+--------+----------+
13 rows in set (0.01 sec)
插入一行再刪除一行
mysql> insert into user_info value(16,‘haha‘,21,‘女‘,3);
Query OK, 1 row affected (0.01 sec)

mysql> delete from user_info where nid=2;
Query OK, 1 row affected (0.01 sec)
mysql> select * from user_info;
+-----+-------+------+--------+----------+
| nid | name  | age  | gender | part_nid |
+-----+-------+------+--------+----------+
|   1 | san   |   18 | 男     |        4 |
|   4 | Ling  |   28 | 男     |        4 |
|   5 | ling  |   28 | 男     |        3 |
|   6 | dong  |   30 | 男     |        1 |
|   7 | b     |   11 | 女     |        1 |
|   8 | c     |   12 | 女     |        1 |
|   9 | d     |   18 | 女     |        4 |
|  11 | f     |   23 | 男     |        2 |
|  12 | dongy |   22 | 男     |        1 |
|  13 | hi    |   18 | 男     |        4 |
|  14 | Hello |   28 | 女     |        2 |
|  15 | hehe  |   22 | 男     |        1 |
|  16 | haha  |   21 | 女     |        3 |
+-----+-------+------+--------+----------+
13 rows in set (0.00 sec)

第二次增量備份:

[root@db backup]# innobackupex --defaults-file=/usr/local/mysql/etc/my.cnf --incremental --user=root --password=redhat  --host=127.0.0.1 /data/backup/ --incremental-basedir=/data/backup/2018-04-01_13-17-21/
註意:這裏的 --incremental-basedir=/data/backup/2018-04-01_13-17-21/ 是上一次增量備份 產生的備份 目錄 
如果基於第一次完整備份 則成為差異備份 

找出最近一次增量備份的binlog文件及信息

cd /data/backup/2018-04-01_13-21-56
[root@db 2018-04-01_13-21-56]# cat xtrabackup_binlog_info 
mysql-bin.000001    17452
備份 mysql-bin.000001 到/data/backup中
[root@db backup]# cd /data/backup
[root@db backup]# cp /data1/mysqldb/mysql-bin.000001 .
[root@db backup]# mysqlbinlog mysql-bin.000001 >binlog.sql

模擬數據庫崩潰數據丟失

[root@db backup]# service mysqld stop
[root@db backup]# rm -rf /data1/mysqldb/*

數據恢復

[root@n1 backup]# ls
2018-04-01_13-13-10     2018-04-01_13-17-21    2018-04-01_13-21-56     binlog.sql    mysql-bin.000001

依次是完全整備份 ,第一次和第二次增量備份 目錄 ,以及備份出來的binlog文件與binlog.sql
恢復過程:
首先對第1個(完整備份)合並只提交事務不回滾 再把第2個目錄合並提交事務不回滾到第一個,再把第3個合並到第1個中;最後做一次回滾,再做統一事務提交;最後再加binlog恢復

完整備份 的事務合並
[root@db backup]# innobackupex --defaults-file=/usr/local/mysql/etc/my.cnf --apply-log --redo-only 2018-04-01_13-13-10/
合並第一次增量事務
[root@db backup]# innobackupex --defaults-file=/usr/local/mysql/etc/my.cnf --apply-log --redo-only 2018-04-01_13-13-10/ --incremental-dir=2018-04-01_13-17-21/
合並第二次增量事務
[root@db backup]# innobackupex --defaults-file=/usr/local/mysql/etc/my.cnf --apply-log --redo-only 2018-04-01_13-13-10/ --incremental-dir=2018-04-01_13-21-56/
合並所有的事務
[root@db backup]# innobackupex --defaults-file=/usr/local/mysql/etc/my.cnf  --apply-log 2018-04-01_13-13-10/
提交還原事務
[root@db backup] innobackupex --defaults-file=/usr/local/mysql/etc/my.cnf  --copy-back 2018-04-01_13-13-10/

修改還原數據權限與啟動數據庫:

[root@db backup]chown mysq.mysql /data1/mysqldb -R
[root@db backup] systemctl start mysqld

binlog事務恢復
mysql> source /data/backup/binlog.sql
mysql> select * from user_info;
+-----+-------+------+--------+----------+
| nid | name | age | gender | part_nid |
+-----+-------+------+--------+----------+
| 1 | san | 18 | 男 | 4 |
| 4 | Ling | 28 | 男 | 4 |
| 5 | ling | 28 | 男 | 3 |
| 6 | dong | 30 | 男 | 1 |
| 7 | b | 11 | 女 | 1 |
| 8 | c | 12 | 女 | 1 |
| 9 | d | 18 | 女 | 4 |
| 11 | f | 23 | 男 | 2 |
| 12 | dongy | 22 | 男 | 1 |
| 13 | hi | 18 | 男 | 4 |
| 14 | Hello | 28 | 女 | 2 |
| 15 | hehe | 22 | 男 | 1 |
| 16 | haha | 21 | 女 | 3 |
+-----+-------+------+--------+----------+
13 rows in set (0.00 sec)

到此增量備份 與恢復 已經 完成!

總結:

日常數據庫的備份是十分有必要的,而且不管用什麽方法恢復,開啟binary log十分重要,否則恢復不完整;binary log最好不要和數據目錄一起,另外建議數據目錄和binary log所在目錄不要放在同一塊物理磁盤;同時需要計劃備份並實現異地備份;這樣出現刪庫跑或崩潰數據丟失時就不怕了!本文很多步驟,可能存在遺漏之處,如有錯誤之處,歡迎指點;

Mysql/Mariadb備份(xtrabackup)還原實戰