# MySQL增量備份與恢復

增量備份概念:

備份自上一次備份以後增長或改變的文件或內容mysql

增量備份的特色:

優勢:沒有重複數據,備分量不大,時間短。sql

缺點:須要上次徹底備份及徹底備份以後全部的增量備份才能恢復,並且對全部增量備份進行逐個反推恢復,操做較爲繁瑣。數據庫

mysql沒有直接提供的增量備份方法,可是能夠經過MySQL的二進制日誌(binary logs)間接實現增量備份。二進制日誌對備份的意義以下:vim

(1)二進制日誌保存了全部更新或者可能更新數據庫的操做。安全

(2)二進制日誌在啓動MySQL服務器後開始記錄,並在文件到達max_binlog_size所設置的大小或者接收到flush-logs命令後從新建立新的日誌文件。服務器

(3) 只須要定時執行fulsh-logs方法從新建立新的日誌,生成二進制文件序列,並及時把這些日誌保存到安全的地方就完成了一個時間段的增量備份。架構

增量備份

1.要進行MySQL增量備份,首先要開啓二進制日誌功能。開啓二進制日誌方法:app

(1)在MySQL配置文件的[mysqld]項中加入log-binfilepath項,如log-bin=mysql-bin,而後重啓mysqld服務。socket

[root@localhost ~]# vim /etc/my.cnf
[mysqld]
user = mysql
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
character_set_server=utf8
log-bin=mysql-bin            //添加項//
pid-file = /usr/local/mysql/mysqld.pid
socket = /usr/local/mysql/mysql.sock
server-id = 1
[root@localhost ~]# systemctl restart mysqld.service     //重啓MySQL服務//

(2)使用mysqladmin的選項flush-logs生成新的二進制文件mysql-bin.000001,這樣在插入新的數據後,新的二進制文件對應的就是數據庫的變化的內容。ide

[root@localhost data]# mysqladmin -uroot -p flush-logs    //增量備份//
[root@localhost data]# ls
auto.cnf        ibdata1      ib_logfile1  kgc    mysql-bin.000001  performance_schema
ib_buffer_pool  ib_logfile0  ibtmp1       mysql  mysql-bin.index   sys

增量恢復

當數據發生錯誤時,應根據實際 狀況選擇使用徹底備份恢復,仍是增量恢復。增量恢復的場景是:

(1)人爲的SQL語句破壞了數據庫。

(2)在進行下一次全備以前發生系統故障致使數據庫數據丟失。

(3)在主從架構中,主庫數據發生了故障。

1.丟失了徹底備份以後更改的數據恢復步驟

(1)首先進入MySQL數據庫中,建立school庫和info表。

[root@localhost data]# mysql -uroot -p   //登陸mysql數據庫//
mysql> create database school;     //建立新的數據庫//
Query OK, 1 row affected (0.01 sec)

mysql> show databases;        //查看數據庫//
+--------------------+
| Database           |
+--------------------+
| information_schema |
| kgc                |
| mysql              |
| performance_schema |
| school             |
| sys                |
+--------------------+
6 rows in set (0.00 sec)
mysql> use school;        //進入數據庫//

(2)向數據庫插入1條數據,退出MySQL數據庫。使用mysqldump徹底備份school庫。

mysql> create table info(name varchar(10),score decimal(5,2)); //建立info表//
mysqlmysql> show tables;   //查看錶信息//
+------------------+
| Tables_in_school |
+------------------+
| info             |
+------------------+
1 row in set (0.00 sec)
mysql> insert into info(name,score) values ('tom',88);  //插入數據//
mysql> select * from info;  //查看數據記錄//
+------+-------+
| name | score |
+------+-------+
| tom  | 88.00 |
+------+-------+
1 row in set (0.00 sec)
[root@localhost data]# mysqldump -uroot -p school > /opt/school.sql //徹底備份school庫//
[root@localhost data]# ls /opt/
school.sql

(3)使用flush-log生成新的二進制文件,用以保存以後的數據庫操做語句。

[root@localhost data]# mysqladmin -uroot -p flush-logs
[root@localhost data]# ls
auto.cnf        ibdata1      ib_logfile1  kgc    mysql-bin.000001  mysql-bin.index     school
ib_buffer_pool  ib_logfile0  ibtmp1       mysql  mysql-bin.000002  performance_schema  sys

(4)再次向數據庫插入1條數據,使用flush-log生成新的二進制文件,用以保存以後的數據庫操做語句。

mysql> insert into info(name,score) values ('abc01',77);  //插入數據//
Query OK, 1 row affected (0.03 sec)

mysql> select * from info;
+-------+-------+
| name  | score |
+-------+-------+
| tom   | 88.00 |
| abc01 | 77.00 |
+-------+-------+
2 rows in set (0.00 sec)
[root@localhost data]# mysqladmin -uroot -p flush-logs  //增量備份//
[root@localhost data]# ls
auto.cnf        ibdata1      ib_logfile1  kgc    mysql-bin.000001  mysql-bin.000003  performance_schema  sys
ib_buffer_pool  ib_logfile0  ibtmp1       mysql  mysql-bin.000002  mysql-bin.index

(6)使用delete刪除插入的1條數據,也就是假設徹底備份後的數據丟失了。

mysql> delete from info where name='abc01';   //刪除數據//
mysql> select * from info;        //查看數據記錄//
+------+-------+
| name | score |
+------+-------+
| tom  | 88.00 |
+------+-------+

(7)使用二進制文件進行增量恢復。

[root@localhost data]# mysqlbinlog --no-defaults mysql-bin.000002 | mysql -u root -p //增量恢復//
[root@localhost data]# mysql -uroot -p    //登陸MySQL數據庫//
mysql> use school;             //進入school庫//
mysql> select * from info;    //查看數據記錄//
+-------+-------+
| name  | score |
+-------+-------+
| tom   | 88.00 |
| abc01 | 77.00 |
+-------+-------+

2.基於時間點與位置的恢復

利用二進制日誌可實現基於時間點與位置的恢復,例如因爲誤操做刪除了一張表,這時徹底恢復是沒有用的,由於日誌裏面還存在誤操做的語句,咱們須要的是恢復到誤操做前的狀態,而後跳過誤操做的語句,再恢復後面操做的語句。

假設須要往數據庫中插入兩條數據,但因爲誤操做,兩條插入語句中間刪除了一條數據,而這條數據是不該該刪除的。

mysql> insert into info(name,score) values ('test01',77); //插入數據test01//
mysql> delete from info where name='tom';                //誤刪除tom數據//
mysql> insert into info(name,score) values ('test02',77);    //插入數據test02//
mysql> select * from info;      //查看數據記錄//
+--------+-------+
| name   | score |
+--------+-------+
| jack   | 88.00 |
| test01 | 77.00 |
| test02 | 77.00 |
+--------+-------+
3 rows in set (0.00 sec)

(1)進行增量備份,編號爲000002的二進制文件中保存了正確的插入語句,同時也保存了不該該執行的刪除語句。

[root@localhost data]# mysqladmin -uroot -p flush-logs  //增量備份//
[root@localhost data]# ls
auto.cnf        ib_logfile1  mysql-bin.000001  performance_schema
ib_buffer_pool  ibtmp1       mysql-bin.000002  school
ibdata1         kgc          mysql-bin.000003  sys
ib_logfile0     mysql        mysql-bin.index

(2)查看編號爲000002的二進制文件,查找誤操做的位置和正確操做的位置,便於進行恢復。

[root@localhost data]# mysqlbinlog --no-defaults --base64-output=decode-rows -v mysql-bin.000002   //查看二進制文件
# at 617     //位置標記//
#180704 17:12:01 server id 1  end_log_pos 660 CRC32 0xe2f72a72  Delete_rows: table id 118 flags: STMT_END_F   //誤操做的起始時間//
### DELETE FROM `school`.`info`   //誤刪的數據//
### WHERE
###   @1='tom'
###   @2=88.00

# at 884   //位置標記//
#180704 17:12:08 server id 1  end_log_pos 930 CRC32 0xd17eb525  Write_rows: table id 118 flags: STMT_END_F  //操做正確的起始時間//
### INSERT INTO `school`.`info`     //插入的數據//
### SET
###   @1='test02'
###   @2=77.00

(3)登陸Mysql數據庫把原有誤刪數據的info表刪除,使用mysql恢復school庫。

mysql> drop table info;   //刪除info表//
mysql> show tables;
Empty set (0.00 sec)

[root@localhost opt]# mysql -u root -p school < /opt/school.sql  //恢復school庫//
[root@localhost opt]# mysql -uroot -p
mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| info             |
+------------------+
1 row in set (0.00 sec)

mysql> select * from info;
+------+-------+
| name | score |
+------+-------+
| tom  | 88.00 |                  //數據tom恢復//
| jack | 88.00 |
+------+-------+
2 rows in set (0.00 sec)

(4)基於時間點的恢復

使用mysqlbinlong加上--stop-datetime選項,表示在哪一個時間點結束,後面誤操做語句不執行,--start-datetime選項表示執行後面的語句,結合使用它們就能夠跳過誤操做的語句,完成恢復工做。須要注意的是,二進制文件中保存的日期格式須要調整爲用「-」分割。

[root@localhost data]# mysqlbinlog --no-defaults --stop-datetime='2018-07-04 17:12:01' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p
[root@localhost opt]# mysql -u root -p
mysql> use school;
mysql> select * from info;
+--------+-------+
| name   | score |
+--------+-------+
| tom    | 88.00 |
| jack   | 88.00 |
| test01 | 77.00 |        //test01數據恢復//
+--------+-------+
3 rows in set (0.00 sec)

[root@localhost data]# mysqlbinlog --no-defaults --start-datetime='2018-07-04 17:12:08' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p
mysql> select * from info;
+--------+-------+
| name   | score |
+--------+-------+
| tom    | 88.00 |
| jack   | 88.00 |
| test01 | 77.00 |
| test02 | 77.00 |       //test02數據恢復//
+--------+-------+
4 rows in set (0.00 sec)

(5)基於位置的恢復

就是使用基於時間點的恢復,可能會出如今一個時間點裏既同時存在正確的操做又存在錯誤的操做,基於位置是一種更爲準確的恢復方式。

①刪除test01和test02數據

mysql> delete from info where name='test01';
mysql> delete from info where name='test02';
mysql> select * from info;
+------+-------+
| name | score |
+------+-------+
| tom  | 88.00 |
| jack | 88.00 |
+------+-------+
2 rows in set (0.00 sec)

②打開編號000002的二進制文件,找到誤操做的位置。

# at 563    //上一次正確操做節點//
#180704 17:12:01 server id 1  end_log_pos 617 CRC32 0x5b03a315  Table_map: `school`.`info` mapped to number 118
# at 617   //誤操做//
#180704 17:12:01 server id 1  end_log_pos 660 CRC32 0xe2f72a72  Delete_rows: table id 118 flags: STMT_END_F
### DELETE FROM `school`.`info`
### WHERE
###   @1='tom'
###   @2=88.00
# at 660   //下一次正確操做節點//
#180704 17:12:01 server id 1  end_log_pos 691 CRC32 0x1230c738  Xid = 37
COMMIT/*!*/;

③第一條插入語句後面的位置是563,--stop-position設置爲563,表示執行第一條插入語句後結束。第二條插入語句後面的位置是660,--start-position設置爲660,表示執行第二條插入語句,跳過了誤操做的刪除語句,達到了恢復數據的目的。

[root@localhost opt]# mysqlbinlog --no-defaults --stop-position='563' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p
[root@localhost opt]# mysqlbinlog --no-defaults --start-position='660' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p
[root@localhost opt]# mysql -uroot -p   //登陸mysql數據庫//
mysql> use school;      //進入school庫//
mysql> select * from info;     //查看數據記錄//
+--------+-------+
| name   | score |
+--------+-------+
| tom    | 88.00 |
| jack   | 88.00 |
| test01 | 77.00 |
| test02 | 77.00 |
+--------+-------+
4 rows in set (0.00 sec)
相關文章
相關標籤/搜索