1. 程式人生 > >Mysql DBA 高級運維學習筆記-MySQL備份與恢復實戰案例及生產方案

Mysql DBA 高級運維學習筆記-MySQL備份與恢復實戰案例及生產方案

人員 副本 and null logs 維護成本 2-0 register pos

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 DBA 高級運維學習筆記-MySQL備份與恢復實戰案例及生產方案