Mysql運維管理-MySQL備份與恢復實戰案例及生產方案17
1.全量備份與增量備份
1.1 全量備份
全量數據就是數據庫中所有的數據,全量備份就是把數據庫中所有的數據進行備份。
備份所有庫:
mysqldump -uroot -p123456 -S /data/3306/mysql.sock -F -B –A gzip >/server/backup/mysq_backup_$(date +%F).sql.gz
備份一個庫:
mysqldump -uroot -p123456 -S /data/3306/mysql.sock -F -B linzhongniao|gzip >/server/backup/mysq_backup_$(date +%F).sql.gz
1.2 增量備份
增量備份是從上次全量備份之後更新的數據,對mysql來說binlog就是增量備份數據。增量備份可以按天備份。第二天做全備了,理論上前一天的備份就沒用了。我們一般主服務器的增量備份一般保持七天,可以通過設置my.cnf配置文件中的expire_logs_days參數讓它的值等於7.備份服務器上增量備份一般保持180天。按天備份就是一天做一次全量備份,每天的零點全量備份,零點之前做增量備份;除了按天全備也可以按周全備,一周做一次全備每天做增量備份。
按天備份的優點:恢復時間:短 維護成本:低
缺點:占用空間多,占用系統資源多,經常鎖表影響用戶體驗。
按周全備的優點:占用空間少,占用系統資源少用戶體驗好一些。
缺點:恢復麻煩維護正本高,時間長。
企業場景全備和增量的頻率是怎麽做的呢?
(1)中小公司,全量一般是每天一次,業務流量低谷執行全備,執行前需要鎖表。
(2)單臺數據庫沒有做主從同步,如何增量。用rsync(配合定時任務頻率大點,或者inotify,主從復制)把所有binlog備份到遠程服務器,盡量做主從復制。
增量備份的例子:
rsync –avz /data/3306/mysql-bin.000* [email protected]::backup –-password-file=/etc/rsync.password
(3)大公司周備,每周六00點一次全量,下周日-下周六00點前都是增量。
有點:節省備份時間,減小備份壓力,缺點:增量的binlog文件副本太多,還原會很麻煩。
(4)一主多從,會有一個從庫做備份,延遲同步。
Mysql的mysqldump備份什麽時候派上用場?
a.遷移或者升級數據庫時。
b.增加從庫的時候。
c.因為硬件或特殊異常情況,主庫或從庫宕機,主從可以切換,無需備份。把其中一個同步最快的切換為主庫即可。
d.人為的DDL、DML語句,主從庫沒辦法了,所有庫都會執行,此時需要備份。
e.跨機房災備,需備份拷貝走數據。
2.MySQL增量恢復必備條件
2.1 開啟MySQL log-bin 日誌功能
[root@mysql ~]# egrep "\[mysqld]|log-bin" /data/3306/my.cnf
[mysqld]
log-bin = /data/3306/mysql-bin
提示:主庫和備份的從庫都需要開啟binlog記錄功能。
小結:增量恢復的條件:
存在一份全備加上全備之後的時刻到出問題時刻的所有增量binlog文件備份。
2.2 存在MySQL數據庫全備
2.2.1 生產環境mysqldump備份命令
在淩晨某一時刻進行數據庫全備(生產場景一般通過定時任務每日淩晨執行),備份命令如下:
mysqldump -uroot -p123456 -S /data/3306/mysql.sock -F -B linzhongniao|gzip >/server/backup/mysq_backup_$(date +%F).sql.gz
innode引擎備份
mysqldump -uroot -p123456 -S /data/3306/mysql.sock --single-transaction -A -B|gzip >/server/backup/mysql_$(date +%F).sql.gz
myisam引擎備份
mysqldump -uroot -p123456 -S /data/3306/mysql.sock --lock-all-tables -A -B|gzip >/server/backup/mysql_$(date +%F).sql.gz
2.3 數據恢復思想
恢復思想就是先找到發生故障的原因,,誰在什麽時候做了什麽操作,檢查是不是這個操作導致數據庫故障。之後盡量停止數據庫對外訪問,先備份0:00到十點更新的數據binlog日誌文件,刷新binlog。第一步先恢復全備,第二步增量恢復0:00到10:00這個時間段的數據。
3.實戰演示數據恢復過程
3.1 執行語句並檢查環境
3.1.1 執行建庫建表語句及插入數據庫語句
[root@mysql ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.5.32-log Source distribution
Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement.
mysql> show variables like ‘%chaeacter_set%‘;
Empty set (0.01 sec)
mysql> create table student(
-> id int(4) not null AUTO_INCREMENT,
-> name char(20) not null,
-> primary key(id)
-> );
Query OK, 0 rows affected (0.01 sec)
mysql> insert into student(name) values(‘nishishei‘);
Query OK, 1 row affected (0.00 sec)
mysql> insert into student(name) values(‘zhangsan‘);
Query OK, 1 row affected (0.00 sec)
mysql> insert into student(name) values(‘lisi‘);
Query OK, 1 row affected (0.00 sec)
3.1.2 檢查數據庫及數據
檢查是否有linzhongniao庫
mysql> show databases like ‘linzhongniao‘;
+-------------------------+
| Database (linzhongniao) |
+-------------------------+
| linzhongniao|
+-------------------------+
1 row in set (0.00 sec)
4.淩晨0點全量備份數據庫
4.1 定時任務數據庫備份腳本
(1) 這裏我們使用MySQL主從復制課程內容裏的備份腳本
#/bin/sh
#Date: 2018-02-11
#Author: Create by linzhongniao
#Mail: [email protected]
#Function:This scripts function is More complex backup scripts, which need to find binlog log files and location points
#Version: 1.1
USER=root
PASS=123456
MYSOCK=/data/3306/mysql.sock
DATA_PATH=/server/backup
DATA_FILE=${DATA_PATH}/mysql_backup_`date +%F`.sql.gz
LOG_FILE=${DATA_PATH}/mysql_backup_`date +%F`.log
MYSQL_PATH=/usr/local/mysql/bin
mysqldb=linzhongniao
#--single-transaction Specifically for the InnoDB engine, when the data is updated when the data is updated, it can‘t see the whole isolation.
MYSQL_DUMP="${MYSQL_PATH}/mysqldump -u$USER -p$PASS -S $MYSOCK --events -B -F --master-data=2 --single-transaction $mysqldb"
MYSQL_CMD="${MYSQL_PATH}/mysql -u$USER -p$PASS -S $MYSOCK"
cat |${MYSQL_CMD}<<EOF
flush table with read lock;
system echo "-----show master status result-----" >>$LOG_FILE;
system ${MYSQL_CMD} -e "show master status"|tail -1 >>$LOG_FILE;
system ${MYSQL_DUMP}|gzip > $DATA_FILE;
unlock tables;
quit
EOF
(2) 執行腳本全量備份linzhongniao庫原理
[root@mysql ~]# date -s ‘2018/02/11‘ 更改系統時間模擬零點時刻
2018年 02月 11日 星期日 00:00:00 CST
[root@mysql ~]# mysqldump -uroot -p123456 -S /data/3306/mysql.sock -F -B --master-data=2 linzhongniao|gzip >/server/backup/bak_$(date +%F).sql.gz
查看備份的數據
[root@mysql ~]# ll /server/backup/
總用量 684
-rw-r--r--. 1 root root203 2月 10 23:26 mysq_backup_2018-02-10.sql.gz
-rw-r--r--. 1 root root 529266 2月 8 19:11 mysql_backup_2018-02-08.sql
-rw-r--r--. 1 root root805 2月 10 23:18 mysql_backup_2018-02-10.sql.gz
-rw-r--r--. 1 root root306 2月 11 00:25 mysql_backup_2018-02-11.log
-rw-r--r--. 1 root root915 2月 11 00:25 mysql_backup_2018-02-11.sql.gz
-rw-r--r--. 1 root root805 2月 10 23:18 mysql_backup_.sql
(3) 實際工作中是通過定時任務來備份的
[root@mysql ~]# crontab –l
#mysql backup by linzhongniao on 20180211
00 00 * * * /bin/sh beifen1.sh >/dev/null 2>&1
4.2 備份後查看binlog日誌情況
[root@mysql ~]# ll /data/3306/
總用量 172
drwxr-xr-x. 8 mysql mysql 4096 2月 12 2018 data
-rw-r--r--. 1 mysql mysql 2099 2月 10 06:48 my.cnf
-rwx------. 1 root root 1126 2月 8 10:10 mysql
-rw-rw----. 1 mysql mysql 1227 2月 8 19:17 mysql-bin.000001
-rw-rw----. 1 mysql mysql 126 2月 9 05:20 mysql-bin.000002
-rw-rw----. 1 mysql mysql 239 2月 9 05:25 mysql-bin.000003
-rw-rw----. 1 mysql mysql 458 2月 9 05:30 mysql-bin.000004
-rw-rw----. 1 mysql mysql 233 2月 9 05:34 mysql-bin.000005
-rw-rw----. 1 mysql mysql 415 2月 9 05:57 mysql-bin.000006
-rw-rw----. 1 mysql mysql 126 2月 9 05:59 mysql-bin.000007
-rw-rw----. 1 mysql mysql 126 2月 9 05:59 mysql-bin.000008
-rw-rw----. 1 mysql mysql 388 2月 9 08:22 mysql-bin.000009
-rw-rw----. 1 mysql mysql 652 2月 10 04:51 mysql-bin.000010
-rw-rw----. 1 mysql mysql 107 2月 10 04:51 mysql-bin.000011
-rw-rw----. 1 mysql mysql 3355 2月 10 06:17 mysql-bin.000012
-rw-rw----. 1 mysql mysql 126 2月 10 06:17 mysql-bin.000013
-rw-rw----. 1 mysql mysql 126 2月 10 06:17 mysql-bin.000014
-rw-rw----. 1 mysql mysql 1914 2月 10 08:34 mysql-bin.000015
-rw-rw----. 1 mysql mysql 150 2月 10 23:18 mysql-bin.000016
-rw-rw----. 1 mysql mysql 150 2月 10 23:18 mysql-bin.000017
-rw-rw----. 1 mysql mysql 126 2月 11 2018 mysql-bin.000018
-rw-rw----. 1 mysql mysql 150 2月 11 00:24 mysql-bin.000019
-rw-rw----. 1 mysql mysql 150 2月 11 00:24 mysql-bin.000020
-rw-rw----. 1 mysql mysql 150 2月 11 00:25 mysql-bin.000021
-rw-rw----. 1 mysql mysql 893 2月 11 01:41 mysql-bin.000022
-rw-rw----. 1 mysql mysql 616 2月 11 00:25 mysql-bin.index
-rw-rw----. 1 mysql mysql 5 2月 12 2018 mysqld.pid
srwxrwxrwx. 1 mysql mysql 0 2月 12 2018 mysql.sock
-rw-r-----. 1 mysql root 42156 2月 12 2018 mysql_zbf3306.err
-rw-rw----. 1 mysql mysql56 2月 11 00:34 relay-bin.index
-rw-rw----. 1 mysql mysql55 2月 11 01:41 relay-log.info
提示:我們可以看用-F參數備份生成的新的文件mysql-bin.000022,增量恢復就是從mysql-bin.000022開始的。
5.備份後模擬用戶繼續更新數據
5.1 模擬網站用戶更新數據
因為在0點備份後到發生故障這個時間段內,用戶還會隨時的更新數據
[root@mysql ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 18
Server version: 5.5.32-log Source distribution
Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement.
mysql> use linzhongniao
Database changed
mysql> insert into student(name) values(‘linzhongniao10‘);
Query OK, 1 row affected (0.35 sec)
mysql> insert into student(name) values(‘linzhongniao11‘);
Query OK, 1 row affected (0.00 sec)
mysql> insert into student(name) values(‘linzhongniao12‘);
Query OK, 1 row affected (0.00 sec)
mysql> select * from student;
+----+----------------+
| id | name |
+----+----------------+
| 1 | nishishei |
| 3 | zhangsan |
| 5 | lisi |
| 6 | burenshi |
| 8 | liushishi |
| 10 | luhan |
| 11 | linzhongniao10 |
| 13 | linzhongniao11 |
| 15 | linzhongniao12 |
+----+----------------+
9 rows in set (0.00 sec)
mysql>
5.2 查看備份後再次更新後的數據庫內容
一會兒我們模擬故障恢復後還應是這些數據,如果不是這些數據就是丟失了數據。
mysql> select * from linzhongniao.student;
+----+----------------+
| id | name |
+----+----------------+
| 1 | nishishei |
| 3 | zhangsan |
| 5 | lisi |
| 6 | burenshi |
| 8 | liushishi |
| 10 | luhan |
| 11 | linzhongniao10 |
| 13 | linzhongniao11 |
| 15 | linzhongniao12 |
+----+----------------+
9 rows in set (0.00 sec)
6.模擬用戶破壞數據庫
6.1 刪除數據庫linzhongniao
公司的老大於早晨10點,執行了刪除數據庫語句。然後跟沒事兒人一樣,本來想刪除一個沒有用的庫。
mysql> drop database linzhongniao;
Query OK, 1 row affected (0.11 sec)
6.2 檢查破壞結果
Linzhongniao庫不見了
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| dfhjdhf|
| mysql |
| performance_schema |
| school |
| test |
+--------------------+
6 rows in set (0.00 sec)
6.3 發現故障排查並檢查原因
數據庫出問題10分鐘後,公司的網站運營人員報網站故障,聯系dba運維人員解決。此時,dba人員或開發人員查看網站報錯(或者查看後臺日誌)。可以看到連不上linzhongniao數據庫的顯示。然後登錄數據庫排查,可以發現數據庫linzhongniao庫確實不在。經過多方詢問得知老大早晨要處理一下數據庫,於是問老大都幹啥了。答曰,10點左右剛剛清除了一個“沒有用的”數據庫。致此問題原因找到,開始準備恢復,原因還有可能是開發人員通過程序日誌判斷。
提示:數據庫的權限管理思想就在這裏。不讓別人有delete權限。
7.增量備份過程
通過防火墻禁止web等應用向主庫寫數據,讓主庫暫停更新,然後進行恢復。
7.1 檢查全備及binlog日誌
7.1.1 檢查淩晨備份
[root@mysql ~]# ll /server/backup/mysql_backup_2018-02-11.*
-rw-r--r--. 1 root root 306 2月 11 00:25 /server/backup/mysql_backup_2018-02-11.log
-rw-r--r--. 1 root root 915 2月 11 00:25 /server/backup/mysql_backup_2018-02-11.sql.gz
7.1.2 檢查全備後的所有binlog
[root@mysql backup]# ls -lrt /data/3306/ >/opt/mysql-bin.txt
[root@mysql backup]# sed -n "21,30p" /opt/mysql-bin.txt
-rw-rw----. 1 mysql mysql 150 2月 11 00:24 mysql-bin.000019
-rw-rw----. 1 mysql mysql 150 2月 11 00:24 mysql-bin.000020
-rw-rw----. 1 mysql mysql 150 2月 11 00:25 mysql-bin.000021
-rw-rw----. 1 mysql mysql 616 2月 11 00:25 mysql-bin.index
-rw-rw----. 1 mysql mysql 253 2月 11 00:34 relay-bin.000023
-rw-rw----. 1 mysql mysql 253 2月 11 00:34 relay-bin.000024
-rw-rw----. 1 mysql mysql56 2月 11 00:34 relay-bin.index
-rw-rw----. 1 mysql mysql 126 2月 11 07:51 mysql-bin.000018
drwxr-xr-x. 7 mysql mysql 4096 2月 11 23:52 data
-rw-rw----. 1 mysql mysql 995 2月 11 23:52 mysql-bin.000022
提示:我們在0點執行的全備,所以binlog日誌文件是從0點往後更新的。我們可以用mysqlbinlog參數查看一下零點之後更新的binlog文件,看看裏面有沒有更新的數據。當然我們也可以通過查看0點全備的數據文件裏面的change master的位置來查看最新更新的binlog文件。可以看到執行全備後的所有binlog日誌文件,它裏面記錄了從0點全備之後到第二天十點所有有更新的數據包括執行的誤操作,所以我們在增量恢復的時候必須把執行誤操作的那條語句刪掉。例如本次演示應該把drop那條語句刪掉。
[root@mysql ~]# grep -i "change" /server/backup/mysql_backup_2018-02-11.sql
-- CHANGE MASTER TO MASTER_LOG_FILE=‘mysql-bin.000022‘, MASTER_LOG_POS=107;
7.1.3 立即刷新並備份出binlog
一般數據庫故障我們要停止數據庫,如果領導說不能停,這種情況下我們要刷新一下binlog。刷新一下binlog就會生成一個新的mysql-bin日誌文件mysql-bin.000023,這時候再更新數據就會往這個新的裏面寫。現在增量恢復的目標就是mysql-bin.000022。
[root@mysql ~]# mysqladmin -uroot -p123456 -S /data/3306/mysql.sock flush-logs
[root@mysql ~]# ls -lrt /data/3306/ >/opt/mysql-bin.txt
[root@mysql ~]# vim /opt/mysql-bin.txt
[root@mysql ~]# sed -n "21,27p" /opt/mysql-bin.txt
-rw-rw----. 1 mysql mysql 150 2月 11 00:24 mysql-bin.000019
-rw-rw----. 1 mysql mysql 150 2月 11 00:24 mysql-bin.000020
-rw-rw----. 1 mysql mysql 150 2月 11 00:25 mysql-bin.000021
-rw-rw----. 1 mysql mysql 126 2月 11 07:51 mysql-bin.000018
drwxr-xr-x. 7 mysql mysql 4096 2月 11 23:52 data
-rw-rw----. 1 mysql mysql 1038 2月 12 01:36 mysql-bin.000022
-rw-rw----. 1 mysql mysql 107 2月 12 01:36 mysql-bin.000023
7.1.4 增量備份binlog
(1)要把mysql-bin.000022拷貝出來防止二次破壞數據
[root@mysql 3306]# cp mysql-bin.000022 /server/backup/
(2)將mysql-bin.000022解析成bin.sql數據文件
[root@mysql backup]# mysqlbinlog -d linzhongniao mysql-bin.000022 >bin.sql
[root@mysql backup]# ll
總用量 24
-rw-r--r--. 1 root root 2868 2月 12 13:45 bin.sql
-rw-r--r--. 1 root root 203 2月 10 23:26 mysq_backup_2018-02-10.sql.gz
-rw-r--r--. 1 root root 306 2月 11 00:25 mysql_backup_2018-02-11.log
-rw-r--r--. 1 root root 2331 2月 11 00:25 mysql_backup_2018-02-11.sql
-rw-r--r--. 1 root root 805 2月 10 23:18 mysql_backup_.sql
-rw-r-----. 1 root root 1038 2月 12 13:41 mysql-bin.000022
8.恢復數據
如果不停庫禁止對外訪問就會有一個問題,什麽問題呢?
第一個問題就是,在恢復的時候還有用戶往數據庫寫數據,mysql-bin.000023還會記錄更新的內容;全備恢復和增量恢復後還要恢復mysql-bin.000023更新的數據,備份mysql-bin.000023還得刷新binlog,增量恢復完mysql-bin.000023還得增量恢復更新的binlog,這樣就死鎖了老得恢復。
第二個問題就是,我們在增量恢復的時候,mysql-bin.000023也會記錄全量和增量恢復的更新。在全量和增量恢復之後再恢復mysql-bin.000023更新的記錄的時候就會導致主鍵沖突,可以編輯mysql-bin.000023解析成的mysql數據文件將沖突的數據刪掉,如果數據多呢?還可以關閉sql_log_bin。關閉sql_log_bin就不會更新binlog日誌文件了,這樣會導致數據缺失。所以這個時候,最好的方法就是挺庫,禁止對外訪問,再做全量和增量備份。最根本的就是數據庫的權限管理,不給刪除修改權限,只有運維的有刪除修改權限,防止故障的發生。誰有權限都要有記錄,誰導致的故障要負責任。
mysql> show variables like ‘%log_bin%‘;
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin | ON|
| log_bin_trust_function_creators | OFF |
| sql_log_bin | ON|
3 rows in set (0.00 sec)
8.1 全量恢復
[root@mysql backup]# ll
總用量 24
-rw-r--r--. 1 root root 2868 2月 12 13:45 bin.sql
-rw-r--r--. 1 root root 203 2月 10 23:26 mysq_backup_2018-02-10.sql.gz
-rw-r--r--. 1 root root 306 2月 11 00:25 mysql_backup_2018-02-11.log
-rw-r--r--. 1 root root 2331 2月 11 00:25 mysql_backup_2018-02-11.sql
-rw-r--r--. 1 root root 805 2月 10 23:18 mysql_backup_.sql
-rw-r-----. 1 root root 1038 2月 12 13:41 mysql-bin.000022
[root@mysql backup]# mysql -uroot -p123456 -S /data/3306/mysql.sock <mysql_backup_2018-02-11.sql
8.2 增量恢復
[root@mysql backup]# mysql -uroot -p123456 -S /data/3306/mysql.sock linzhongniao <bin.sql
8.3 檢查恢復後的數據
mysql> select * from linzhongniao.student;
+----+----------------+
| id | name |
+----+----------------+
| 1 | nishishei |
| 3 | zhangsan |
| 5 | lisi |
| 6 | burenshi |
| 8 | liushishi |
| 10 | luhan |
| 11 | linzhongniao10 |
| 13 | linzhongniao11 |
| 15 | linzhongniao12 |
+----+----------------+
9 rows in set (0.00 sec)
9.增量恢復小結
1.人為SQL造成的誤操作
2.全量和增量
3.恢復時建議對外停止更新
4.恢復全量,然後把增量日誌中有問題的SQL語句刪除,恢復到數據庫。
增量恢復的核心思想:
1.流程制度的控制,如果不做,面臨服務和數據,魚和熊掌不可兼得。
2.可以通過延遲備份來解決或者通過監控,黑名單(不加where的語句是不讓執行),白名單機制。
3.業務需求容忍度,選擇停庫,根據業務需求選擇停庫或鎖表或者容忍丟失部分數據。
Mysql運維管理-MySQL備份與恢復實戰案例及生產方案17