MySQL備份(基於xtrabackup)的實戰

MySQL備份策略

MySQL備份是我們運維過程中再正常不過的事情了,這裏總結一下以前備份的方法,使用的是xtrabackup,當然這裏的備份方法還有mysqldump這個是mysql自己的備份工具,不過它支持的比較簡單,僅支持全量+binlog進行恢復,對於數據量大的企業,你總不能每週兩三次的全量備份+二進制日誌做時間點還原吧,顯然這裏我們需要增量備份的支持;
MySQL備份(基於xtrabackup)的實戰

簡單說一下全量,增量,二進制日誌分別的意思:

比如A數據庫

    週一這天數據一共10g
    週二這天數據一共12g

全量:也就是對週一這天數據庫當前的10g數據,進行全部備份,也叫完整備份,但數據比較大恢復比較慢

增量:增量也就是週二這天數據一共12g,和上次差異相比+2g數據,由於我們昨天做了一次全量備份,今天只需要備份今天的2g就可以了(mysqldump不能這樣,他只能昨天10g,今天再備個12g)

注:差異和增量概念有點模糊,可以自行百科

二進制日誌:用於記錄引起數據改變或存在引起數據改變的潛在可能性的語句(STATEMENT)或改變後的結果(ROW),也可能是二者混合;

(也就是說你的但凡能夠引起數據變化的增刪改都會在這有記錄,我們一般做時間點還原用,因爲比如你晚上2點剛增量完成,3點時候後數據庫崩潰了,那麼2點到3點之間我們是沒有任何備份策略的,好在數據庫的變化都在二進制中有記錄,我們可以將二進制日誌中2-3點的記錄提取出來,當做備份使用)

MySQL日誌分類

在數據庫日誌中,分爲6類(*表示重點,建議開啓):

查詢日誌:general_log    
        記錄信息:
            記錄查詢語句,日誌存儲位置:
                文件:file
                表:table (mysql.general_log)
        打開方法:
            general_log={ON|OFF}
            general_log_file=HOSTNAME.log 
            log_output={FILE|TABLE|NONE}

*慢查詢日誌:log_slow_queries
        慢查詢:運行時間超出指定時長的查詢;
            long_query_time
        存儲位置:
            文件:FILE
            表:TABLE,mysql.slog_log

            log_slow_queries={ON|OFF}
            slow_query_log={ON|OFF}
            slow_query_log_file=
            log_output={FILE|TABLE|NONE}            
            log_slow_filter=admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk
            log_slow_rate_limit
            log_slow_verbosity

*錯誤日誌:log_error, log_warnings   
        記錄信息:
            (1) mysqld啓動和關閉過程 輸出的信息; 
            (2) mysqld運行中產生的錯誤信息; 
            (3) event scheduler運行時產生的信息;
            (4) 主從複製架構中,從服務器複製線程啓動時產生的日誌;
        打開方法:
            log_error=/var/log/mariadb/mariadb.log|OFF
            log_warnings={ON|OFF}

*二進制日誌:binlog       但凡能夠引起數據變化的增刪改都會在這
        打開方法:
            log_bin=/PATH/TO/BIN_LOG_FILE   只讀變量;
            session.sql_log_bin={ON|OFF}    控制某會話中的“寫”操作語句是否會被記錄於binlog日誌文件中;
            max_binlog_size=1073741824      單位爲字節,這裏爲1G,binlog單個最大
            sync_binlog={1|0}               控制數據庫的binlog刷到磁盤上去,1是每次事務提交,MySQL都會把binlog刷下到磁盤,是最安全但是性能損耗最大的設置,0是由文件系統自己控制它的緩存的刷新。這時候的性能是最好的,但是風險也是最大的。因爲一旦系統Crash,在binlog_cache中的所有binlog信息都會被丟失爲,0和設置爲1的系統寫入性能差距可能高達5倍甚至更多。

中繼日誌:relay_log      從服務器上記錄下來從主服務器的二進制日誌文件同步過來的事件,主從模式纔會用到;
事務日誌:innodb_log     innodb事務日誌包括redo log和undo log。
    redo log是重做日誌,提供前滾操作,
    undo log是回滾日誌,提供回滾操作。

備份的必要性和注意點

備份時應該注意事項:
    能容忍最多丟失多少數據;
    恢復數據需要在多長時間內完成;
    需要恢復哪些數據;

備份需要考慮因素:
    鎖定資源多長時間?
    備份過程的時長?
    備份時的服務器負載?
    恢復過程的時長?

mysqldump介紹和示例

上面是一些簡單的敘述,這裏也捎帶着提一下mysqldump的備份參數,但不做細細分析

mysqldump:
    mysqldump是一個單進程的備份工具,同一時刻內只能備份一個表
    mysqldump的備份原理是查詢當前要備份的數據庫表的所有數據,全部轉換成插入語句

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

        InnoDB存儲引擎:支持溫備和熱備;
                --single-transaction:創建一個事務,基於此快照執行備份;

其它選項(建議必選):
        -R, --routines:存儲過程和存儲函數;
        --triggers      觸發器
        -E, --events    事件
        --master-data[=#]
            1:記錄爲CHANGE MASTER TO語句,此語句不被註釋;
            2:記錄爲CHANGE MASTER TO語句,此語句被註釋;用於查看下次binlog恢復時,應基於哪個位置開始恢復

        --flush-logs:備份時鎖定表完成後,即進行日誌新文件滾動刷新;方便binlog恢復時,我們基於上次備份sql和一個新的binlog文件恢復

mysqldump的備份示例:

備份hellodb數據庫,myisam引擎,由於不支持事務和表空間序列號,只能溫備(只讀不能寫)或冷備
    MyISAM:
        備份hellodb庫中的new表:
            mysqldump -uroot -proot -R -E --triggers --master-data=2 --flush-logs -l hellodb new > /data1/hellodb-fullback-$(%data +%F).sql 
            ##表恢復時,若原始庫不存在,不會自動創建庫,需要自己先創建庫

        備份一個庫:
            mysqldump -uroot -proot -R -E --triggers --master-data=2 --flush-logs -l hellodb > /data1/hellodb-fullback-$(%data +%F).sql
        備份所有庫:
            mysqldump -uroot -proot -R -E --triggers --master-data=2 --flush-logs -x --all-databases > /data1/alldb-fullback-$(%data +%F).sql

備份hellodb數據庫,INNODB引擎,支持事務和表空間序列號,這裏做熱備(熱備的選擇根據是否會影響當前業務,因爲會對服務器造成負載,對業務影響先評估)MyISAM的參數-x/-l仍然支持
    InnoDB:
        備份hellodb庫中的new表:
            mysqldump -uroot -proot -R -E --triggers --master-data=2 --flush-logs --single-transaction hellodb new > /data1/hellodb-fullback-$(%data +%F).sql
        備份一個庫:
            mysqldump -uroot -proot -R -E --triggers --master-data=2 --flush-logs --single-transaction hellodb > /data1/hellodb-fullback-$(%data +%F).sql
        備份所有庫:
            mysqldump -uroot -proot -R -E --triggers --master-data=2 --flush-logs --single-transaction --all-databases > /data1/alldb-fullback-$(%data +%F).sql

還原數據時:
        進入mysql先關閉binlog的記錄:set @@session.sql_log_bin=OFF;
        當還原完成時應及時馬上做一次全量備份,若業務緊急上線,也應做熱備全備

binlog恢復:
        mysqlbinlog master-01.00005 > binlog.sql

Xtrabackup備份

Xtrabackup是一個對InnoDB做數據備份的工具,支持在線熱備份(備份時不影響數據讀寫),是商業備份工具InnoDB Hotbackup的一個很好的替代品。

默認安裝xtrabackup會有innobackupex命令和xtrabackup,我們一般使用innobackupex,但其實innobackupex也是軟連接的xtrabackup

軟件包提供:鏈接:https://pan.baidu.com/s/1Ay42kAecCgJhyqAClKM0CA 密碼:w7fe

或者去官網下載最新版:https://www.percona.com/

InnoDB全量+binlog

完整備份:

innobackupex --defaults-file=/etc/my.cnf --user=root --password=root ~/     ##完整備份
MariaDB [(none)]> INSERT INTO hellodb.students values (26,'ifan',19,'M',6,1);   ##插入數據

模擬故障:

systemctl stop mariadb
cp /var/lib/mysql/DB-bin.* /data/
rm -rf /var/lib/mysql/*

數據恢復:

cd 2019-03-05_22-22-19/         ##進入全備
innobackupex --apply-log ./     ##由於這是全備沒有差異備份和增量備份,所以不考慮未完成的事務,進行合併lsn,並回滾未完成事務

innobackupex --copy-back ./     ##lsn合併和事務回滾後,進行還原數據
chown -R mysql.mysql /var/lib/mysql     ##重新設置屬主屬組權限

systemctl start mariadb         ##啓動數據庫即可

根據binlog增量恢復:

[root@localhost 2019-03-05_22-22-19]# cat xtrabackup_binlog_info        ##查看全備完成的位置
DB-bin.000003   9116
[root@localhost 2019-03-05_22-22-19]# mysqlbinlog -j 9116 /data/DB-bin.000003 > binlog.sql
[root@localhost 2019-03-05_22-22-19]# mysql -uroot -proot
MariaDB [(none)]> set @@session.sql_log_bin=OFF;
MariaDB [(none)]> source binlog.sql                 ##還原binlog.sql,恢復第26條內容
MariaDB [(none)]> select * from hellodb.students;
+-------+---------------+-----+--------+---------+-----------+
| StuID | Name          | Age | Gender | ClassID | TeacherID |
+-------+---------------+-----+--------+---------+-----------+
|     1 | Shi Zhongyu   |  22 | M      |       2 |         3 |
|     2 | Shi Potian    |  22 | M      |       1 |         7 |
                        .........
|    24 | Xu Xian       |  27 | M      |    NULL |      NULL |
|    25 | Sun Dasheng   | 100 | M      |    NULL |      NULL |
|    26 | ifan          |  19 | M      |       6 |         1 |
+-------+---------------+-----+--------+---------+-----------+
26 rows in set (0.00 sec)
[root@localhost ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=root ~/     ##還原完成後,馬上基於本次立即做全備
[root@localhost ~]# ls
2019-03-05_23-19-54

InnoDB全量+增量+binlog

我們先做一次全量備份:
[root@localhost ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=root ~/
[root@localhost ~]# ls
2019-03-06_00-04-44 
刪除一部分數據
[root@localhost ~]# mysql -uroot -proot
MariaDB [hellodb]> delete from students where StuID='10';  
Query OK, 1 row affected (0.00 sec)

[root@localhost ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=root --incremental ~/ --incremental-basedir=~/2019-03-06_00-04-44/      ##進行增量備份
[root@localhost ~]# ls
2019-03-06_00-04-44  2019-03-06_00-09-25
查看全量的xtrabackup_checkpoints文件記錄的lsn值:
[root@localhost ~]# cat 2019-03-06_00-04-44/xtrabackup_checkpoints
backup_type = full-backuped ##全量備份
from_lsn = 0            ##由於我這個是新還原的數據庫,所以起始位置爲0
to_lsn = 1634678        
last_lsn = 1634678
compact = 0
recover_binlog_info = 0
[root@localhost ~]# cat 2019-03-06_00-09-25/xtrabackup_checkpoints
backup_type = incremental   ##增量備份
from_lsn = 1634678      ##增量備份的起始位置應該是繼承上次備份的位置
to_lsn = 1635829        ##這裏是本次備份的最後備份位置1635829,下次增量起始位置將緊接着這個位置
last_lsn = 1635829
compact = 0
recover_binlog_info = 0

緊接着我們再刪除一個ID爲20的同學,再做一次增量備份:
MariaDB [(none)]> delete from hellodb.students where StuID='20';    
Query OK, 1 row affected (0.00 sec)
[root@localhost ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=root --incremental ~/ --incremental-basedir=~/2019-03-06_00-09-25/      ##這次增量要基於上次增量的位置
[root@localhost ~]# ls      
2019-03-06_00-04-44  2019-03-06_00-09-25  2019-03-06_00-16-41
##查看新備份的增量的xtrabackup_checkpoints
[root@localhost ~]# cat 2019-03-06_00-16-41/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 1635829          ##這裏的起始位置是上次增量的位置以此類推
to_lsn = 1637002
last_lsn = 1637002
compact = 0
recover_binlog_info = 0

緊接着我們再插入一個值,用binlog恢復:

MariaDB [(none)]> INSERT INTO hellodb.students values (30,'xiaopingfan',19,'M',6,1);
Query OK, 1 row affected (0.00 sec)

爲了我們binlog恢復:
我們要將最近一次增量備份最後的binlog位置找到,這樣我們才能恢復最近一次增量到數據庫崩潰時之間的數據:
首先查看最近一次binlog備份的最後位置:
[root@localhost ~]# cat 2019-03-06_00-16-41/xtrabackup_binlog_info 
DB-bin.000001   8132        
[root@localhost ~]# cp /var/lib/mysql/DB-bin.000001 /root/      ##將這段二進制日誌備份出來
[root@localhost ~]# mysqlbinlog -j 8132 DB-bin.000001 > binlog.sql      ##轉化成sql

開始恢復:

systemctl stop mariadb
rm -rf /var/lib/mysql/*
這裏我們一共產生一次全量備份和兩次增量備份,我們要先將全量備份的事務合併(已完成的事務進行合併,未完成的事務不處理,等待後續的增量備份事務進行合併),然後將兩次增量(有順序)的備份進行依次合併到全量備份上,最後再合併一次全量備份(已完成的事務進行合併,未完成的事務由於後續沒有了增量備份,未完成的事務就進行回滾,不能讓其生效)
記住,在合併的時候就像三堆土,既然要並在一次,肯定是兩小堆依次合併在那一堆大的土堆上面

增量開始恢復:
[root@localhost ~]# innobackupex --defaults-file=/etc/my.cnf --apply-log --redo-only 2019-03-06_00-04-44/           ##已完成的事務進行合併,未完成的事務不處理,等待後續的增量備份事務進行合併

[root@localhost ~]# innobackupex --defaults-file=/etc/my.cnf --apply-log --redo-only 2019-03-06_00-04-44/ --incremental-dir=2019-03-06_00-09-25/        ##將第一次增量合併到全量上

[root@localhost ~]# innobackupex --defaults-file=/etc/my.cnf --apply-log --redo-only 2019-03-06_00-04-44/ --incremental-dir=2019-03-06_00-16-41/        ##將第二次增量合併到全量上

[root@localhost ~]# innobackupex --defaults-file=/etc/my.cnf --apply-log 2019-03-06_00-04-44/   ##所有的增量恢復完,最後對全備已完成的事務進行合併,未完成的事務回滾

[root@localhost ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back 2019-03-06_00-04-44/
[root@localhost ~]# chown -R mysql.mysql /var/lib/mysql
[root@localhost ~]# systemctl start mariadb
[root@localhost ~]# mysql -uroot -proot
MariaDB [(none)]> set @@session.sql_log_bin=OFF;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> show binary logs;
+---------------+-----------+
| Log_name      | File_size |
+---------------+-----------+
| DB-bin.000001 |       245 |
+---------------+-----------+
1 row in set (0.00 sec)

MariaDB [(none)]> source binlog.sql
Query OK, 0 rows affected (0.00 sec)
...
Query OK, 0 rows affected (0.00 sec)

查看xiaopingfan是否存在:

MariaDB [(none)]> select * from hellodb.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 |        16 |
|     4 | Ding Dian     |  32 | M      |       4 |         4 |
|     5 | Yu Yutong     |  26 | M      |       3 |         1 |
|     6 | Shi Qing      |  46 | M      |       5 |      NULL |
|     7 | Xi Ren        |  19 | F      |       3 |      NULL |
|     8 | Lin Daiyu     |  17 | F      |       7 |      NULL |
|     9 | Ren Yingying  |  20 | F      |       6 |      NULL |
|    11 | Yuan Chengzhi |  23 | M      |       6 |      NULL |
|    12 | Wen Qingqing  |  19 | F      |       1 |      NULL |
|    13 | Tian Boguang  |  33 | M      |       2 |      NULL |
|    14 | Lu Wushuang   |  17 | F      |       3 |      NULL |
|    15 | Duan Yu       |  19 | M      |       4 |      NULL |
|    16 | Xu Zhu        |  21 | M      |       1 |      NULL |
|    17 | Lin Chong     |  25 | M      |       4 |      NULL |
|    18 | Hua Rong      |  23 | M      |       7 |      NULL |
|    19 | Xue Baochai   |  18 | F      |       6 |      NULL |
|    21 | Huang Yueying |  22 | F      |       6 |      NULL |
|    22 | Xiao Qiao     |  20 | F      |       1 |      NULL |
|    23 | Ma Chao       |  23 | M      |       4 |      NULL |
|    24 | Xu Xian       |  27 | M      |    NULL |      NULL |
|    25 | Sun Dasheng   | 100 | M      |    NULL |      NULL |
|    30 | xiaopingfan   |  19 | M      |       6 |         1 |
+-------+---------------+-----+--------+---------+-----------+
24 rows in set (0.00 sec)

數據恢復完成,馬上對此次回覆完成的數據庫做一次全量備份:
[root@localhost ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=root ~/

--apply-log ##分析獲取binary log文件生成backup_binlog_info文件
--redo-only ##只提交已完成事務
--copy-back ##還原數據庫

注:如果庫中有MyISAM引擎的表,庫中如果有innodb和myisam和innodb並存,xtrabackup方法下按照innodb備份即可,由於innodb引擎的增量備份是基於LSN來實現的,myisam不支持事務和lsn所以對於myisam表每次都是全量備份,對於innodb表則是增量備份

查看數據庫內所有表引擎腳本:

#!/bin/bash

myuser='root'
mypass='root'
myport=3306

base_list=`mysql -u${myuser} -p${mypass} -P${myport} -e "show databases;"|egrep -v 'mysql|Database|information_schema|performance_schema'`           ##得到庫列表
for k in ${base_list};
do
table_list=`mysql -u${myuser} -p${mypass} -P${myport} -e "use ${k};show tables;"|egrep -v 'Tables_in'`                               ##得到表列表
        for g in ${table_list};
        do

ccmd=`mysql -u${myuser} -p${mypass} -P${myport} -e "show table status from ${k} where name='${g}'\G"|egrep -w Engine|awk -F ':' '{print $2}'`
        echo -e "數據庫:${k} 下 ${g}表的引擎爲: ${ccmd}"
        done
done
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章