MySQL的二進制日誌(binlog)使用分析(4)——利用binlog日誌恢復數據
利用binlog日誌恢復數據,就是讓mysql將保存在binlog日誌中指定段落區間的SQL語句重新執行一次而已。
下面通過一個例子說明怎樣例如binlog日誌恢復數據:
一、數據庫信息
1、數據庫:hist,wanggx
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hist |
| mysql |
| performance_schema |
| sys |
| wanggx |
+--------------------+
6 rows in set (0.01 sec)
2、hist數據庫包含的表
mysql> use hist;
Database changed
mysql> show tables;
+----------------+
| Tables_in_hist |
+----------------+
| course |
| dept |
| score |
| stu |
+----------------+
4 rows in set (0.00 sec)
3、wanggx數據庫包含的表
mysql> use wanggx;
Database changed
mysql> show tables;
+------------------+
| Tables_in_wanggx |
+------------------+
| department |
| emp |
+------------------+
2 rows in set (0.00 sec)
二、備份策略
在每天凌晨四點對hist和wanggx數據庫進行一次完全備份,命令如下:
mysqldump -uroot -p123456 --databases -F -R -x --master-data=2 hist wanggx | gzip >/data_bak/db_bak_$(date +%F).sql.gz
參數說明:
(1)–databases(-B):指定要備份的數據庫名稱;
(2)-F:刷新日誌;
(3)-R:備份存儲過程等;
(4)-x:鎖表;
(5)–master-data:在備份語句裏添加CHANGE MASTER語句以及binlog文件及位置點信息。
在全備份的時候使用-F選項,當數據備份操作開始時,系統就會自動刷新log,會自動產生一個新的binlog日誌,這個新的binlog日誌用來記錄備份之後對數據庫的【增、刪、改】操作。
查看備份結果:
[root@Mysql11 data_bak]# mysqldump -uroot -p123456 --databases -F -R -x --master-data=2 hist wanggx | gzip >/data_bak/db_bak_$(date +%F).sql.gz
mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@Mysql11 data_bak]# ls /data_bak/
db_bak_2020-07-04.sql.gz
查看備份結束後的日誌信息:
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000012 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
說明:從日誌文件mysql-bin.000012開始記錄上次備份之後對數據庫的所有修改操作信息。
由於備份時使用了【–master-data】選項,在備份語句裏添加CHANGE MASTER語句以及binlog文件及位置點信息。
[root@Mysql11 data_bak]# cat db_bak_2020-07-04.sql
-- MySQL dump 10.13 Distrib 5.7.27, for Linux (x86_64)
--
...............
--
-- Position to start replication or point-in-time recovery from
--
#### CHANGE MASTER語句、binlog文件及位置點信息
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000012', MASTER_LOG_POS=154;
--
-- Current Database: `hist`
--
...........
三、備份之後修改數據
1、修改hist數據庫中的stu表的數據
(1)上次數據備份之後,hist數據庫中的stu表數據如下:
mysql> use hist;
Database changed
mysql> select * from stu;
+----+----------+------+-----------+-------------+---------+
| id | name | age | address | phone | dept_id |
+----+----------+------+-----------+-------------+---------+
| 1 | zhangsan | 21 | Xinxiang | 15578941258 | 1 |
| 2 | tom | 20 | Xinxiang | 13778942222 | 1 |
| 3 | jack | 21 | Zhengzhou | 13675871454 | 1 |
| 4 | john | 22 | Zhengzhou | 13937681111 | 2 |
| 5 | mark | 22 | Aanyang | 13055882233 | 2 |
+----+----------+------+-----------+-------------+---------+
5 rows in set (0.01 sec)
(2)對hist數據庫中的stu表進行如下操作:
mysql> insert into stu(name,age,address,phone,dept_id) values('Obama',18,'America','13988886666',3);
Query OK, 1 row affected (0.01 sec)
mysql> insert into stu(name,age,address,phone,dept_id) values('Trump',19,'America','13066668888',3);
Query OK, 1 row affected (0.01 sec)
mysql> update stu set age=age+1 where dept_id=2;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> delete from stu where id=1;
Query OK, 1 row affected (0.01 sec)
(3)修改之後的數據如下:
mysql> select * from stu;
+----+-------+------+-----------+-------------+---------+
| id | name | age | address | phone | dept_id |
+----+-------+------+-----------+-------------+---------+
| 2 | tom | 20 | Xinxiang | 13778942222 | 1 |
| 3 | jack | 21 | Zhengzhou | 13675871454 | 1 |
| 4 | john | 23 | Zhengzhou | 13937681111 | 2 |
| 5 | mark | 23 | Aanyang | 13055882233 | 2 |
| 6 | Obama | 18 | America | 13988886666 | 3 |
| 7 | Trump | 19 | America | 13066668888 | 3 |
+----+-------+------+-----------+-------------+---------+
6 rows in set (0.00 sec)
2、修改wanggx數據庫中的department表的數據
(1)上次數據備份之後,wanggx數據庫中的department表數據如下:
mysql> use wanggx
Database changed
mysql> select * from department;
+---------+----------+
| dept_id | name |
+---------+----------+
| 1 | guanli |
| 2 | jingji |
| 3 | jidian |
| 4 | jisuanji |
+---------+----------+
4 rows in set (0.01 sec)
(2)對wanggx數據庫中的department表進行如下修改:
mysql> insert into department(name) values('huagong');
Query OK, 1 row affected (0.00 sec)
mysql> insert into department(name) values('yishu');
Query OK, 1 row affected (0.03 sec)
(3)修改後的數據如下:
mysql> select * from department;
+---------+----------+
| dept_id | name |
+---------+----------+
| 1 | guanli |
| 2 | jingji |
| 3 | jidian |
| 4 | jisuanji |
| 5 | huagong |
| 6 | yishu |
+---------+----------+
6 rows in set (0.01 sec)
四、模擬誤操作
由於業務部熟練或者不小心執行了如下操作:
1、刪除hist庫
mysql> drop database hist;
Query OK, 4 rows affected (0.05 sec)
2、創建hist庫和t1表,並插入數據
mysql> create database hist;
Query OK, 1 row affected (0.01 sec)
mysql> use hist;
Database changed
mysql> create table t1(id int primary key,name char(20));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t1 values(1,'a');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values(2,'b');
Query OK, 1 row affected (0.02 sec)
五、把數據庫恢復刪除hist數據庫之前的狀態
1、查看上次備份之後的binlog日誌文件名稱以及位置點信息
[root@Mysql11 data_bak]# cat db_bak_2020-07-04.sql
-- MySQL dump 10.13 Distrib 5.7.27, for Linux (x86_64)
--
...............
--
-- Position to start replication or point-in-time recovery from
--
#### CHANGE MASTER語句、binlog文件及位置點信息
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000012', MASTER_LOG_POS=154;
--
-- Current Database: `hist`
--
...........
查詢結果爲:日誌文件爲【mysql-bin.000012】,位置點爲【154】。
2、備份binlog文件【mysql-bin.000012】及以後的binlog文件
(1)查看binlog日誌文件的信息
mysql> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 923 |
| mysql-bin.000002 | 703 |
| mysql-bin.000003 | 201 |
| mysql-bin.000004 | 542 |
| mysql-bin.000005 | 518 |
| mysql-bin.000006 | 201 |
| mysql-bin.000007 | 448 |
| mysql-bin.000008 | 201 |
| mysql-bin.000009 | 1595 |
| mysql-bin.000010 | 201 |
| mysql-bin.000011 | 201 |
| mysql-bin.000012 | 3456 |
+------------------+-----------+
12 rows in set (0.00 sec)
(2)發現只需要備份【mysql-bin.000012】一個文件即可
[root@Mysql11 data_bak]# cp /var/lib/mysql/mysql-bin.000012 /data_bak/
[root@Mysql11 data_bak]# ls /data_bak/
db_bak_2020-07-04.sql mysql-bin.000012
3、刷新日誌索引操作,重新開始新的binlog日誌文件
爲了便於我們分析原因,以後所有數據庫操作都會寫入到下一個日誌文件。
mysql> flush logs;
Query OK, 0 rows affected (0.01 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000013 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
4、查看binlog日誌,找到刪除hist數據庫的位置
查看binlog日誌文件的信息
mysql> show binlog events in '/var/lib/mysql/mysql-bin.000012';
+------------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------------+
| mysql-bin.000012 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.27-log, Binlog ver: 4 |
| mysql-bin.000012 | 123 | Previous_gtids | 1 | 154 | |
| mysql-bin.000012 | 154 | Anonymous_Gtid | 1 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000012 | 219 | Query | 1 | 291 | BEGIN |
| mysql-bin.000012 | 291 | Rows_query | 1 | 407 | # insert into stu(name,age,address,phone,dept_id) values('Obama',18,'America','13988886666',3) |
| mysql-bin.000012 | 407 | Table_map | 1 | 464 | table_id: 136 (hist.stu) |
| mysql-bin.000012 | 464 | Write_rows | 1 | 538 | table_id: 136 flags: STMT_END_F |
| mysql-bin.000012 | 538 | Xid | 1 | 569 | COMMIT /* xid=405 */ |
| mysql-bin.000012 | 569 | Anonymous_Gtid | 1 | 634 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000012 | 634 | Query | 1 | 706 | BEGIN |
| mysql-bin.000012 | 706 | Rows_query | 1 | 822 | # insert into stu(name,age,address,phone,dept_id) values('Trump',19,'America','13066668888',3) |
| mysql-bin.000012 | 822 | Table_map | 1 | 879 | table_id: 136 (hist.stu) |
| mysql-bin.000012 | 879 | Write_rows | 1 | 953 | table_id: 136 flags: STMT_END_F |
| mysql-bin.000012 | 953 | Xid | 1 | 984 | COMMIT /* xid=406 */ |
| mysql-bin.000012 | 984 | Anonymous_Gtid | 1 | 1049 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000012 | 1049 | Query | 1 | 1121 | BEGIN |
| mysql-bin.000012 | 1121 | Rows_query | 1 | 1185 | # update stu set age=age+1 where dept_id=2 |
| mysql-bin.000012 | 1185 | Table_map | 1 | 1242 | table_id: 136 (hist.stu) |
| mysql-bin.000012 | 1242 | Update_rows | 1 | 1298 | table_id: 136 flags: STMT_END_F |
| mysql-bin.000012 | 1298 | Xid | 1 | 1329 | COMMIT /* xid=407 */ |
| mysql-bin.000012 | 1329 | Anonymous_Gtid | 1 | 1394 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000012 | 1394 | Query | 1 | 1466 | BEGIN |
| mysql-bin.000012 | 1466 | Rows_query | 1 | 1516 | # delete from stu where id=1 |
| mysql-bin.000012 | 1516 | Table_map | 1 | 1573 | table_id: 136 (hist.stu) |
| mysql-bin.000012 | 1573 | Delete_rows | 1 | 1613 | table_id: 136 flags: STMT_END_F |
| mysql-bin.000012 | 1613 | Xid | 1 | 1644 | COMMIT /* xid=408 */ |
| mysql-bin.000012 | 1644 | Anonymous_Gtid | 1 | 1709 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000012 | 1709 | Query | 1 | 1783 | BEGIN |
| mysql-bin.000012 | 1783 | Rows_query | 1 | 1853 | # insert into department(name) values('huagong') |
| mysql-bin.000012 | 1853 | Table_map | 1 | 1911 | table_id: 137 (wanggx.department) |
| mysql-bin.000012 | 1911 | Write_rows | 1 | 1959 | table_id: 137 flags: STMT_END_F |
| mysql-bin.000012 | 1959 | Xid | 1 | 1990 | COMMIT /* xid=422 */ |
| mysql-bin.000012 | 1990 | Anonymous_Gtid | 1 | 2055 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000012 | 2055 | Query | 1 | 2129 | BEGIN |
| mysql-bin.000012 | 2129 | Rows_query | 1 | 2197 | # insert into department(name) values('yishu') |
| mysql-bin.000012 | 2197 | Table_map | 1 | 2255 | table_id: 137 (wanggx.department) |
| mysql-bin.000012 | 2255 | Write_rows | 1 | 2301 | table_id: 137 flags: STMT_END_F |
| mysql-bin.000012 | 2301 | Xid | 1 | 2332 | COMMIT /* xid=423 */ |
| mysql-bin.000012 | 2332 | Anonymous_Gtid | 1 | 2397 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
|
############## 刪除hist數據庫的位置2397#################################################
| mysql-bin.000012 | 2397 | Query | 1 | 2489 | drop database hist |
#######################################################################################
| mysql-bin.000012 | 2489 | Anonymous_Gtid | 1 | 2554 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000012 | 2554 | Query | 1 | 2648 | create database hist |
| mysql-bin.000012 | 2648 | Anonymous_Gtid | 1 | 2713 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000012 | 2713 | Query | 1 | 2836 | use `hist`; create table t1(id int primary key,name char(20)) |
| mysql-bin.000012 | 2836 | Anonymous_Gtid | 1 | 2901 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000012 | 2901 | Query | 1 | 2973 | BEGIN |
| mysql-bin.000012 | 2973 | Rows_query | 1 | 3025 | # insert into t1 values(1,'a') |
| mysql-bin.000012 | 3025 | Table_map | 1 | 3073 | table_id: 141 (hist.t1) |
| mysql-bin.000012 | 3073 | Write_rows | 1 | 3115 | table_id: 141 flags: STMT_END_F |
| mysql-bin.000012 | 3115 | Xid | 1 | 3146 | COMMIT /* xid=433 */ |
| mysql-bin.000012 | 3146 | Anonymous_Gtid | 1 | 3211 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000012 | 3211 | Query | 1 | 3283 | BEGIN |
| mysql-bin.000012 | 3283 | Rows_query | 1 | 3335 | # insert into t1 values(2,'b') |
| mysql-bin.000012 | 3335 | Table_map | 1 | 3383 | table_id: 141 (hist.t1) |
| mysql-bin.000012 | 3383 | Write_rows | 1 | 3425 | table_id: 141 flags: STMT_END_F |
| mysql-bin.000012 | 3425 | Xid | 1 | 3456 | COMMIT /* xid=434 */ |
| mysql-bin.000012 | 3456 | Rotate | 1 | 3503 | mysql-bin.000013;pos=4 |
+------------------+------+----------------+-----------+-------------+------------------------------------------------------------------------------------------------+
57 rows in set (0.00 sec)
也可以使用mysqlbinlog -v來查找。
5、先把上次全備的數據恢復
(1)恢復數據
[root@Mysql11 data_bak]# mysql -uroot -p123456 < /data_bak/db_bak_2020-07-04.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
(2)查看數據
mysql> use hist;
Database changed
mysql> select * from stu;
+----+----------+------+-----------+-------------+---------+
| id | name | age | address | phone | dept_id |
+----+----------+------+-----------+-------------+---------+
| 1 | zhangsan | 21 | Xinxiang | 15578941258 | 1 |
| 2 | tom | 20 | Xinxiang | 13778942222 | 1 |
| 3 | jack | 21 | Zhengzhou | 13675871454 | 1 |
| 4 | john | 22 | Zhengzhou | 13937681111 | 2 |
| 5 | mark | 22 | Aanyang | 13055882233 | 2 |
+----+----------+------+-----------+-------------+---------+
5 rows in set (0.00 sec)
mysql> use wanggx;
Database changed
mysql> show tables;
+------------------+
| Tables_in_wanggx |
+------------------+
| department |
| emp |
+------------------+
2 rows in set (0.00 sec)
mysql> select * from department;
+---------+----------+
| dept_id | name |
+---------+----------+
| 1 | guanli |
| 2 | jingji |
| 3 | jidian |
| 4 | jisuanji |
+---------+----------+
4 rows in set (0.00 sec)
6、恢復上次全備之後對數據進行的修改
(1)恢復刪除hist數據庫之前的操作
[root@Mysql11 data_bak]# mysqlbinlog --stop-position=2397 /var/lib/mysql/mysql-bin.000012 > /data_bak/hist_before.sql
[root@Mysql11 data_bak]#
[root@Mysql11 data_bak]# mysql -uroot -p123456 -e "source /data_bak/hist_before.sql"
mysql: [Warning] Using a password on the command line interface can be insecure.
查看數據:
mysql> use hist;
Database changed
mysql> select * from stu;
+----+-------+------+-----------+-------------+---------+
| id | name | age | address | phone | dept_id |
+----+-------+------+-----------+-------------+---------+
| 2 | tom | 20 | Xinxiang | 13778942222 | 1 |
| 3 | jack | 21 | Zhengzhou | 13675871454 | 1 |
| 4 | john | 23 | Zhengzhou | 13937681111 | 2 |
| 5 | mark | 23 | Aanyang | 13055882233 | 2 |
| 6 | Obama | 18 | America | 13988886666 | 3 |
| 7 | Trump | 19 | America | 13066668888 | 3 |
+----+-------+------+-----------+-------------+---------+
6 rows in set (0.00 sec)
mysql> use wanggx
Database changed
mysql> select * from department;
+---------+----------+
| dept_id | name |
+---------+----------+
| 1 | guanli |
| 2 | jingji |
| 3 | jidian |
| 4 | jisuanji |
| 5 | huagong |
| 6 | yishu |
+---------+----------+
6 rows in set (0.00 sec)
(2)恢復刪除hist數據庫之後的操作
[root@Mysql11 data_bak]# mysql -uroot -p123456 -e "use hist;drop table t1;"
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@Mysql11 data_bak]# mysqlbinlog --start-position=2648 /var/lib/mysql/mysql-bin.000012 > /data_bak/hist_after.sql
[root@Mysql11 data_bak]# mysql -uroot -p123456 -e "source /data_bak/hist_after.sql"
mysql: [Warning] Using a password on the command line interface can be insecure.
查看數據:
mysql> use hist;
Database changed
mysql> show tables;
+----------------+
| Tables_in_hist |
+----------------+
| course |
| dept |
| score |
| stu |
| t1 |
+----------------+
5 rows in set (0.00 sec)
mysql> select * from t1;
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
+----+------+
2 rows in set (0.00 sec)