MySQL數據恢復實踐

MySQL數據增量恢復實踐

第1章 系統環境

1.1 操作系統版本

查看操作系統的版本信息如下:

[root@mysql01 ~]# cat /etc/redhat-release
CentOS release 6.5 (Final)
[root@mysql01 ~]# uname -r
2.6.32-431.el6.x86_64
[root@mysql01 ~]# uname -m
x86_64

1.2 MySQL數據庫版本

查看數據庫的版本信息如下:

mysql> select version();
+------------+
| version()  |
+------------+
| 5.5.32-log |
+------------+
1 row in set (0.00 sec)

1.3 主機環境

主機名

IP地址

mysql01

192.168.1.102

mysql02

192.168.1.103

1.4 數據模擬

1.4.1 mysql01

該數據庫作爲數據恢復的測試庫,無任何數據。

1.4.2 mysql02

新建一個數據庫,數據庫名爲test,添加如下三個測試表:student(學生表),course(課程表),sc(選課表)。

q  創建數據庫:

mysql> create database test character set utf8 collate utf8_general_ci;     #<==創建test數據庫並設定字符集爲uft8;
Query OK, 1 row affected (0.00 sec)
 
mysql> show create database test;   #<==查看創建數據庫的命令


+----------+---------------------------------------------------------------+
| Database | Create Database                                               |
+----------+---------------------------------------------------------------+
| test     | CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+---------------------------------------------------------------+
1 row in set (0.00 sec)

q  創建表

mysql> use test;            #<==切換到test數據庫

Database changed

 

(1)創建student表:

drop table student;
create table student(
Sno int(10) NOT NULL COMMENT '學號',
Sname varchar(16) NOT NULL COMMENT '姓名',
Ssex char(2) NOT NULL COMMENT '姓別',
Sage tinyint(2) NOT NULL default '0' COMMENT '學生年齡',
Sdept varchar(16) default NULL COMMENT '學生所在系別',
PRIMARY KEY (Sno),
key index_name(Sname)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

 

(2)創建course表:

drop table course;
create table course(
Cno int(10) NOT NULL COMMENT '課程號',
Cname varchar(64) NOT NULL COMMENT '課程名',
Ccredit tinyint(2) NOT NULL COMMENT '學分',
PRIMARY KEY (Cno)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

 

(3)創建SC表

drop table SC;
create table SC(
SCid int(12) NOT NULL auto_increment COMMENT '主鍵',
Cno int(10) NOT NULL COMMENT '課程號',
Sno int(10) NOT NULL COMMENT '學號',
Grade tinyint(2) NOT NULL COMMENT '學生成績',
PRIMARY KEY (SCid)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

q  查看錶結構

使用desc table的命令查看錶結構:

mysql> desc student;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| Sno   | int(10)     | NO   | PRI | NULL    |       |
| Sname | varchar(16) | NO   | MUL | NULL    |       |
| Ssex  | char(2)     | NO   |     | NULL    |       |
| Sage  | tinyint(2)  | NO   |     | 0       |       |
| Sdept | varchar(16) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

 

mysql> desc course;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| Cno     | int(10)     | NO   | PRI | NULL    |       |
| Cname   | varchar(64) | NO   |     | NULL    |       |
| Ccredit | tinyint(2)  | NO   |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

 

mysql> desc SC;
+-------+------------+------+-----+---------+----------------+
| Field | Type       | Null | Key | Default | Extra          |
+-------+------------+------+-----+---------+----------------+
| SCid  | int(12)    | NO   | PRI | NULL    | auto_increment |
| Cno   | int(10)    | NO   |     | NULL    |                |
| Sno   | int(10)    | NO   |     | NULL    |                |
| Grade | tinyint(2) | NO   |     | NULL    |                |
+-------+------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

q  插入表數據

(1)student表

INSERT INTO student values(0001, '宏志', '男',30, '計算機網絡');
INSERT INTO student values(0002, '王鎖', '男',30, 'computer application');
INSERT INTO student values(0003, 'oldboy', '男',28, '物流管理');
INSERT INTO student values(0004, '脈動', '男',29, 'computer application');
INSERT INTO student values(0005, 'oldgirl', '女',26, '計算機科學與技術');
INSERT INTO student values(0006, '瑩瑩', '女',22, '計算機護士');

 

(2)course表

INSERT INTO course values(1001, 'linux中高級運維',3);
INSERT INTO course values(1002, 'linux高級架構師',5);
INSERT INTO course values(1003, 'linux高級DBA',4);
INSERT INTO course values(1004, 'Python運維開發',4);
INSERT INTO course values(1005, 'Java web開發',3);

 

(3)SC表

INSERT INTO SC(Sno,Cno,Grade) values(0001,1001,4);
INSERT INTO SC(Sno,Cno,Grade) values(0001,1002,3);
INSERT INTO SC(Sno,Cno,Grade) values(0001,1003,1);
INSERT INTO SC(Sno,Cno,Grade) values(0001,1004,4);
INSERT INTO SC(Sno,Cno,Grade) values(0002,1001,3);

q  查看錶數據插入結果

mysql> select * from student;
+-----+---------+------+------+--------------------------+
| Sno | Sname   | Ssex | Sage | Sdept                    |
+-----+---------+------+------+--------------------------+
|   1 | 宏志    | 男   |   30 | 計算機網絡               |
|   2 | 王鎖    | 男   |   30 | computer applica         |
|   3 | oldboy  | 男   |   28 | 物流管理                 |
|   4 | 脈動    | 男   |   29 | computer applica         |
|   5 | oldgirl | 女   |   26 | 計算機科學與技術         |
|   6 | 瑩瑩    | 女   |   22 | 計算機護士               |
+-----+---------+------+------+--------------------------+
6 rows in set (0.00 sec)

 

mysql> select * from course;
+------+----------------------+---------+
| Cno  | Cname                | Ccredit |
+------+----------------------+---------+
| 1001 | linux中高級運維      |       3 |
| 1002 | linux高級架構師      |       5 |
| 1003 | linux高級DBA         |       4 |
| 1004 | Python運維開發       |       4 |
| 1005 | Java web開發         |       3 |
+------+----------------------+---------+
5 rows in set (0.00 sec)

 

mysql> select * from SC;
+------+------+-----+-------+
| SCid | Cno  | Sno | Grade |
+------+------+-----+-------+
|    1 | 1001 |   1 |     4 |
|    2 | 1002 |   1 |     3 |
|    3 | 1003 |   1 |     1 |
|    4 | 1004 |   1 |     4 |
|    5 | 1001 |   2 |     3 |
+------+------+-----+-------+
5 rows in set (0.00 sec)

模擬數據創建完畢!!

第2章 數據恢復條件

2.1 全量備份數據文件

要對數據進行恢復,首先是要有備份的數據。爲了防患於未然,我們需要定期對數據庫進行全量備份。一般而言,我們可以通過執行定時任務對數據進行備份。

2.1.1 備份工具mysqldump

mysqldumpmysql自帶的一個很好用的數據庫備份命令,關鍵參數如下:

參數

含義

-B

備份多個庫(添加createuse語句)

-A

備份所有庫

-d

只備份庫表結構

-t

只備份數據,無庫表結構(sql語句形式)

-T

分離庫表和數據稱不同的文件,數據是文本,非SQL語句

-F

刷新binlog日誌文件,生成新文件,將來增量恢復從這個文件開始!!

--master-data=value

增加binlog日誌文件名及對應的位置點。value=1,不註釋;value=2註釋;

-x

--lock-all-tables,鎖表

-l

--lock-tables,只讀鎖表

-q

--quick

-R

routines,指定轉存的例程

 

2.1.2 全庫整庫備份

對整個數據庫服務器的所有數據庫進行備份,備份命令如下:

mysqldump -uroot -p123456 -S /data/3306/mysql.sock -A -B -F -R -x --master-data=2|gzip > /backup/all_$(date +%F).sql.gz

注:|gzip表示對備份文件進行壓縮,壓縮率大概爲1/3

2.1.3 分數據庫備份(推薦)

推薦使用分庫備份的方式來進行備份,可以編寫一個簡單的shell腳本來實現該功能,簡單腳本示例如下:

#!/bin/bash
 
password="123456"
user="root"
port="3306"
bakpath=/backup
database=`mysql -u$user -p$password -S /data/$port/mysql.sock -e "show databases;"| egrep -v "Database|_schema|mysql"`
 
for n in $database
do
  mysqldump -u$user -p$password -S /data/$port/mysql.sock -B -F -R -x --master-data=2 $n | gzip > ${bakpath}/${n}_$(date +%F).sql.gz
done

2.1.4 定時執行備份腳本

可以設置定時任務每天凌晨1:00備份數據庫,定時任務設置如下:

00 01 * * * /bin/sh /service/scripts/backup.sh &>/dev/null

2.2 增量備份數據文件

除了定時全備數據庫外,還需要數據庫增量數據。該功能是通過binlog日誌文件實現的。

2.2.1 binlog日誌文件介紹

binlog日誌作用是用來記錄mysql內部增刪改等對mysql數據庫有更新的內容的記錄(對數據庫的改動),對數據庫查詢的語句如showselect開頭的語句,不會被binlog日誌記錄。用於數據庫的增量恢復,以及主從複製。

q  binlog的三種模式

(1)    ROW Level

日誌中會記錄成每一行數據被修改的形式,然後在slave端再對相同的數據進行修改。

(2)    Statement Level

每一條會修改數據的sql都會記錄到masterbin-log中。slave在複製的時候sql進程會解析成和原來master端執行過程相同的sql來再次執行。

(3)    Mixed

實際上就是前兩種模式的結合。在Mixed模式下,MySQL會根據執行的每一條具體的sql語句來區分對待記錄的日誌形式,也就是在statementRow之間選擇一種。

2.2.2 開啓log-bin日誌功能

mysql配置文件裏面添加如下參數開啓該功能:

[root@mysql02 backup]# grep "log-bin" /data/3306/my.cnf

log-bin = /data/3306/mysql-bin          #<==開啓binlog功能

2.3 條件小結

增量恢復的條件:存在一份全備之後的時刻到出問題的所有增量的binlog文件備份!!

第3章 數據庫的恢復

場景:在一次做完全量備份之後,數據庫test被無情的刪除,期間有數據的增量寫入。

3.1 環境模擬

3.1.1 執行一次全被(分庫備份)

[root@mysql02 backup]# sh /service/scripts/test.sh      #<==直接執行腳本,腳本如上所示
[root@mysql02 backup]# ll
total 4
-rw-r--r-- 1 root root 1442 Feb  6 11:17 test_2018-02-06.sql.gz     #<==備份的test庫數據

3.1.2 寫入新的數據到SC

對錶SC重新寫入3條數據,之前是5條。

mysql> use test;
 
INSERT INTO SC(Sno,Cno,Grade) values(0002,1002,2);
INSERT INTO SC(Sno,Cno,Grade) values(0002,1003,2);
INSERT INTO SC(Sno,Cno,Grade) values(0002,1004,8);
 
mysql> select * from SC;        #<==更新過後有8條數據了
+------+------+-----+-------+
| SCid | Cno  | Sno | Grade |
+------+------+-----+-------+
|    1 | 1001 |   1 |     4 |
|    2 | 1002 |   1 |     3 |
|    3 | 1003 |   1 |     1 |
|    4 | 1004 |   1 |     4 |
|    5 | 1001 |   2 |     3 |
|    6 | 1002 |   2 |     2 |
|    7 | 1003 |   2 |     2 |
|    8 | 1004 |   2 |     8 |
+------+------+-----+-------+
8 rows in set (0.00 sec)

3.1.3 刪除數據庫

寫入數據之後,刪除test數據庫:

mysql> drop database test;
Query OK, 3 rows affected (0.00 sec)
 
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)

3.2 全量數據恢復

3.2.1 解壓gz數據文件

由於打包時是將數據文件壓縮了,因此需要將壓縮後的文件解壓才能使用,解壓如下:

[root@mysql02 backup]# ll
total 4
-rw-r--r-- 1 root root 1442 Feb  6 11:17 test_2018-02-06.sql.gz     #<==這是一個gz文件
[root@mysql02 backup]# gzip -d test_2018-02-06.sql.gz       #<==解壓命令,最好先做個備份
[root@mysql02 backup]# ll
total 8
-rw-r--r-- 1 root root 4283 Feb  6 11:17 test_2018-02-06.sql    #<==解壓過後的文件

3.2.2 恢復數據

恢復數據有兩種方式,任意選擇其中一種即可(推薦直接使用mysql命令):

方法一、直接通過mysql命令導入sql文件

[root@mysql02 backup]# mysql -uroot -p123456 -S /data/3306/mysql.sock < /backup/test_2018-02-06.sql 
[root@mysql02 backup]# mysql -uroot -p123456 -S /data/3306/mysql.sock -e "show databases;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+

方法二、登陸MySQL數據庫過後,使用source恢復文件

mysql -uroot -p123456 -S /data/3306/mysql.sock
mysql> source /backup/test_2018-02-06.sql       #<==使用source 備份文件直接恢復


這一步驟完成之後已經恢復到全備時間點的數據了!!!

[root@mysql02 backup]# mysql -uroot -p123456 -S /data/3306/mysql.sock -e "use test;select * from SC;"
+------+------+-----+-------+
| SCid | Cno  | Sno | Grade |
+------+------+-----+-------+
|    1 | 1001 |   1 |     4 |
|    2 | 1002 |   1 |     3 |
|    3 | 1003 |   1 |     1 |
|    4 | 1004 |   1 |     4 |
|    5 | 1001 |   2 |     3 |
+------+------+-----+-------+

3.3 增量數據恢復

3.3.1 找到binlog文件

從數據庫全被到數據庫恢復的這段時間內,已經生成了多個的binglog文件,那麼如何找到具體的文件呢?最好的辦法就是通過對應的時間點來查找!!通過備份命令生成備份文件的時候,會有一個時間點,如下:

[root@mysql02 backup]# ll
total 8
-rw-r--r-- 1 root root 4283 Feb  6 11:17 test_2018-02-06.sql

可以看出是在11:17分做的備份,那麼我們就可以找從11:17開始往後的binlog文件了:

[root@mysql02 backup]# ll /data/3306/
total 632
drwxr-xr-x 5 mysql mysql   4096 Feb  6 11:28 data
-rw-r--r-- 1 mysql mysql   2043 Jan 29 13:52 my.cnf
-rwx------ 1 mysql mysql   1110 Jan 29 13:50 mysql
-rw-r----- 1 mysql root   15803 Feb  5 16:04 mysql_3306.err
-rw-rw---- 1 mysql mysql    537 Jan 31 10:35 mysql-bin.000001
-rw-rw---- 1 mysql mysql    126 Jan 31 10:38 mysql-bin.000002
-rw-rw---- 1 mysql mysql    402 Jan 31 10:46 mysql-bin.000003
-rw-rw---- 1 mysql mysql    403 Jan 31 10:50 mysql-bin.000004
-rw-rw---- 1 mysql mysql    126 Jan 31 10:52 mysql-bin.000005
-rw-rw---- 1 mysql mysql   2256 Feb  5 15:57 mysql-bin.000006
-rw-rw---- 1 mysql mysql    126 Feb  5 15:59 mysql-bin.000007
-rw-rw---- 1 mysql mysql    264 Feb  5 16:01 mysql-bin.000008
-rw-rw---- 1 mysql mysql    477 Feb  5 16:03 mysql-bin.000009
-rw-rw---- 1 mysql mysql   7496 Feb  5 16:53 mysql-bin.000010
-rw-rw---- 1 mysql mysql 536268 Feb  6 09:54 mysql-bin.000011
-rw-rw---- 1 mysql mysql    150 Feb  6 10:16 mysql-bin.000012
-rw-rw---- 1 mysql mysql    150 Feb  6 10:17 mysql-bin.000013
-rw-rw---- 1 mysql mysql    237 Feb  6 10:18 mysql-bin.000014
-rw-rw---- 1 mysql mysql    150 Feb  6 10:18 mysql-bin.000015
-rw-rw---- 1 mysql mysql    235 Feb  6 11:17 mysql-bin.000016
-rw-rw---- 1 mysql mysql   7468 Feb  6 11:28 mysql-bin.000017
-rw-rw---- 1 mysql mysql    476 Feb  6 11:17 mysql-bin.index
-rw-rw---- 1 mysql mysql      6 Feb  5 16:04 mysqld.pid
srwxrwxrwx 1 mysql mysql      0 Feb  5 16:04 mysql.sock

可以直觀的看出11:17以後的有mysql-bin.000017一個文件!

注:實現備份時切割刷新binlog文件是通過-F 參數指定的,所以在備份的時候要注意使用-F參數。這裏也可能有多個文件,具體按實際情況

3.3.2 合併binlog文件

binlog文件默認是二進制文件無法讀取,所以我們需要先將這些binlog文件轉換爲一個可讀的SQL文件,而這一步驟可以通過mysqlbinlog命令來實現!!具體實現過程如下:

[root@mysql02 backup]# cp /data/3306/mysql-bin.000017 . #<==先將binlog文件拷貝到其他地方,注意備份

使用mysqlbinlog命令合併

 [root@mysql02 backup]# mysqlbinlog -d test mysql-bin.000017 >> recover.sql

注:1、這裏的-d test是指定數據庫。MySQL能識別binlog文件的最小單位就是數據庫了,無法通過參數來識別具體的表。

    2、合併時要注意順序,需按照遞增的順序來合併!!

3.3.3 刪除SQL文件的錯誤語句

合併成一個文件之後,將錯誤的SQL命令刪除,否則你重新執行的時候會將錯誤的命令再次執行,會出現一系列的問題!

注:這裏需要在每條insert語句後面加一個;

SET TIMESTAMP=1517887356/*!*/;
drop database test          #<==這條就是誤操作的命令,將之刪除再做恢復操作!!!!
/*!*/;
# at 893

3.3.4 恢復增量數據

使用合併的文件來恢復增量數據,注意需要制定數據庫,因爲binlog裏面是沒有use 數據庫語句的。

[root@mysql02 backup]# mysql -uroot -p123456 -S /data/3306/mysql.sock test < recover.sql

3.3.5 查看數據恢復情況

到上一步爲止,數據的恢復工作基本已經完畢,這時候查看一下數據是否恢復正常!!

[root@mysql02 backup]# mysql -uroot -p123456 -S /data/3306/mysql.sock -e "use test;select * from SC;"
+------+------+-----+-------+
| SCid | Cno  | Sno | Grade |
+------+------+-----+-------+
|    1 | 1001 |   1 |     4 |
|    2 | 1002 |   1 |     3 |
|    3 | 1003 |   1 |     1 |
|    4 | 1004 |   1 |     4 |
|    5 | 1001 |   2 |     3 |
|    6 | 1002 |   2 |     2 |
|    7 | 1003 |   2 |     2 |
|    8 | 1004 |   2 |     8 |
+------+------+-----+-------+
增量數據恢復完畢!!!


第4章 單表的恢復

單表的恢復和上面類似,只不過不能直接導入SQL文件,需要將之轉化爲單表的SQL語句在導入。

4.1 grep日誌文件恢復

4.1.1 過濾出SQL文件中單表的操作語句

使用grep 表明的形式,將binlog轉換的SQL文件裏面對應表的語句都篩選出來,再導入數據庫中!

[root@mysql02 backup]# grep SC recover.sql          #<==過濾單表操作語句
INSERT INTO SC(Sno,Cno,Grade) values(0002,1002,2)
INSERT INTO SC(Sno,Cno,Grade) values(0002,1003,2)
INSERT INTO SC(Sno,Cno,Grade) values(0002,1004,8)
grep SC recover.sql > SC.sql

 

4.1.2 使用單表文件恢復

mysql -uroot -p123456 -S /data/3306/mysql.sock test < SC.sql
[root@mysql02 backup]# mysql -uroot -p123456 -S /data/3306/mysql.sock -e "use test;select * from SC;"
+------+------+-----+-------+
| SCid | Cno  | Sno | Grade |
+------+------+-----+-------+
|    1 | 1001 |   1 |     4 |
|    2 | 1002 |   1 |     3 |
|    3 | 1003 |   1 |     1 |
|    4 | 1004 |   1 |     4 |
|    5 | 1001 |   2 |     3 |
|    6 | 1002 |   2 |     2 |
|    7 | 1003 |   2 |     2 |
|    8 | 1004 |   2 |     8 |
+------+------+-----+-------+

4.2 測試庫重新導出

先將全被和增被數據都導入到測試庫裏面,步驟同全量恢復數據。再此不重複操作。

4.2.1 導出表SQL文件

恢復好全庫數據後,使用mysqldump命令將單表的SQL語句導出

mysqldump -uroot -p123456 -S /data/3307/mysql.sock -F -x test SC > sc.sql

4.2.2 恢復單表

將單表的SC.sql文件轉移到需恢復的數據庫,進行數據恢復!

mysql -uroot -p123456 -S /data/3306/mysql.sock test < SC.sql
[root@mysql02 backup]# mysql -uroot -p123456 -S /data/3306/mysql.sock -e "use test;select * from SC;"
+------+------+-----+-------+
| SCid | Cno  | Sno | Grade |
+------+------+-----+-------+
|    1 | 1001 |   1 |     4 |
|    2 | 1002 |   1 |     3 |
|    3 | 1003 |   1 |     1 |
|    4 | 1004 |   1 |     4 |
|    5 | 1001 |   2 |     3 |
|    6 | 1002 |   2 |     2 |
|    7 | 1003 |   2 |     2 |
|    8 | 1004 |   2 |     8 |
+------+------+-----+-------+

數據庫恢復測試完畢!!!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章