# MySQL增量備份與恢復
備份自上一次備份之後增加或改變的文件或內容
增量備份的特點:
優點:沒有重復數據,備份量不大,時間短。
缺點:需要上次完全備份及完全備份之後所有的增量備份才能恢復,而且對所有增量備份進行逐個反推恢復,操作較為繁瑣。
mysql沒有直接提供的增量備份方法,但是可以通過MySQL的二進制日誌(binary logs)間接實現增量備份。二進制日誌對備份的意義如下:
(1)二進制日誌保存了所有更新或者可能更新數據庫的操作。
(2)二進制日誌在啟動MySQL服務器後開始記錄,並在文件到達max_binlog_size所設置的大小或者接收到flush-logs命令後重新創建新的日誌文件。
(3) 只需要定時執行fulsh-logs方法重新創建新的日誌,生成二進制文件序列,並及時把這些日誌保存到安全的地方就完成了一個時間段的增量備份。
增量備份
1.要進行MySQL增量備份,首先要開啟二進制日誌功能。開啟二進制日誌方法:
(1)在MySQL配置文件的[mysqld]項中加入log-binfilepath項,如log-bin=mysql-bin,然後重啟mysqld服務。
[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,這樣在插入新的數據後,新的二進制文件對應的就是數據庫的變化的內容。
[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)
# MySQL增量備份與恢復