利用binlog日志恢复数据,就是让mysql将保存在binlog日志中指定段落区间的SQL语句重新执行一次而已。
下面通过一个例子说明怎样例如binlog日志恢复数据:
在每天凌晨四点对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)由于备份时使用了【–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表数据如下:
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)(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)由于业务部熟练或者不小心执行了如下操作:
查询结果为:日志文件为【mysql-bin.000012】,位置点为【154】。
(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为了便于我们分析原因,以后所有数据库操作都会写入到下一个日志文件。
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)查看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来查找。
(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)(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)