如何用binlog日志恢复MySQL误删数据
从学习数据库以来,我接触数据库后在日常学习中理解了 “从删库到跑路” 这句话的重要性。
终于我学到了用binlog文件恢复数据来避免这个问题,我使用的流程如下(要求:必须是centos环境下安装的MySQL):
1.让我们先创建、插入数据(此时一定记得检查日志功能是否开启,具体参照第3步);
mysql> select * from reader;
+------+---------------+---------+--------------+
| rid | rName | lendNum | rAddress |
+------+---------------+---------+--------------+
| 001 | zhangYongwei | 2 | 北京西城 |
| 002 | zhangDawei | 1 | 北京东城 |
| 3 | jixiegongye | 10 | 北京南 |
| 4 | zhangchongkun | 10 | 北京北 |
| 5 | wangdaxian | 10 | 北京西 |
| 6 | liergou | 10 | 北京南 |
+------+---------------+---------+--------------+
6 rows in set (0.00 sec)
2.破坏数据,并查看;
mysql> delete from reader where rid = 6;
Query OK, 1 row affected (0.00 sec)
mysql> select * from reader;
+------+---------------+---------+--------------+
| rid | rName | lendNum | rAddress |
+------+---------------+---------+--------------+
| 001 | zhangYongwei | 2 | 北京西城 |
| 002 | zhangDawei | 1 | 北京东城 |
| 3 | jixiegongye | 10 | 北京南 |
| 4 | zhangchongkun | 10 | 北京北 |
| 5 | wangdaxian | 10 | 北京西 |
+------+---------------+---------+--------------+
5 rows in set (0.00 sec)
mysql>
3.这里就开始做恢复步骤了,先检查日志功能是否打开,用到代码(这里一定要在创建数据前就提前开启日志功能):
show variables like '%log_bin%';
显示如下:log_bin 与 sql_log_bin 均为 on即为开启,若未开启输入:
# set lon_bin = on 与 # set sql_log_bin = on 即可开启,显示如下:
mysql> show variables like '%log_bin%';
+---------------------------------+-----------------------------+
| Variable_name | Value |
+---------------------------------+-----------------------------+
| log_bin | ON |
| log_bin_basename | /var/lib/mysql/binlog |
| log_bin_index | /var/lib/mysql/binlog.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+-----------------------------+
6 rows in set (0.01 sec)
mysql>
4.查看最新一次生成的log文件的编号,这里由于是刚删的就在新生成的log文件里面,若删的时间过早就得自己找了,用到的命令是:
show master logs;
mysql> show master logs;
+---------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000001 | 821 | No |
| binlog.000002 | 12268 | No |
| binlog.000003 | 200 | No |
| binlog.000004 | 1759 | No |
+---------------+-----------+-----------+
4 rows in set (0.01 sec)
mysql>
5.查到指定log文件后就可以查看里面的pos了(每个用户的文件名不一,我的是binlog.000004)
show binlog events in 'binlog.000004';
查询结果:
mysql> show binlog events in 'binlog.000004';
+---------------+------+----------------+-----------+-------------+--------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+---------------+------+----------------+-----------+-------------+--------------------------------------+
| binlog.000004 | 4 | Format_desc | 1 | 125 | Server ver: 8.0.25, Binlog ver: 4 |
| binlog.000004 | 125 | Previous_gtids | 1 | 156 | |
| binlog.000004 | 156 | Anonymous_Gtid | 1 | 235 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| binlog.000004 | 235 | Query | 1 | 313 | BEGIN |
| binlog.000004 | 313 | Table_map | 1 | 382 | table_id: 93 (library.reader) |
| binlog.000004 | 382 | Write_rows | 1 | 447 | table_id: 93 flags: STMT_END_F |
| binlog.000004 | 447 | Xid | 1 | 478 | COMMIT /* xid=14 */ |
| binlog.000004 | 478 | Anonymous_Gtid | 1 | 557 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| binlog.000004 | 557 | Query | 1 | 635 | BEGIN |
| binlog.000004 | 635 | Table_map | 1 | 704 | table_id: 93 (library.reader) |
| binlog.000004 | 704 | Write_rows | 1 | 771 | table_id: 93 flags: STMT_END_F |
| binlog.000004 | 771 | Xid | 1 | 802 | COMMIT /* xid=15 */ |
| binlog.000004 | 802 | Anonymous_Gtid | 1 | 881 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| binlog.000004 | 881 | Query | 1 | 959 | BEGIN |
| binlog.000004 | 959 | Table_map | 1 | 1028 | table_id: 93 (library.reader) |
| binlog.000004 | 1028 | Write_rows | 1 | 1092 | table_id: 93 flags: STMT_END_F |
| binlog.000004 | 1092 | Xid | 1 | 1123 | COMMIT /* xid=16 */ |
| binlog.000004 | 1123 | Anonymous_Gtid | 1 | 1202 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| binlog.000004 | 1202 | Query | 1 | 1280 | BEGIN |
| binlog.000004 | 1280 | Table_map | 1 | 1349 | table_id: 93 (library.reader) |
| binlog.000004 | 1349 | Write_rows | 1 | 1410 | table_id: 93 flags: STMT_END_F |
| binlog.000004 | 1410 | Xid | 1 | 1441 | COMMIT /* xid=17 */ |
| binlog.000004 | 1441 | Anonymous_Gtid | 1 | 1520 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| binlog.000004 | 1520 | Query | 1 | 1598 | BEGIN |
| binlog.000004 | 1598 | Table_map | 1 | 1667 | table_id: 93 (library.reader) |
| binlog.000004 | 1667 | Delete_rows | 1 | 1728 | table_id: 93 flags: STMT_END_F |
| binlog.000004 | 1728 | Xid | 1 | 1759 | COMMIT /* xid=20 */ |
+---------------+------+----------------+-----------+-------------+--------------------------------------+
27 rows in set (0.00 sec)
注意:这里需要找到的是我们创建数据时的pos而不是删数据时的pos,我们创建数据这个操作是连续的所以Info里面的xid也是连续的;
同时起始pos是开始创建的xid上最近的BEGIN对应的,结束pos是终止的xid下面最近的SET对应的,找错的话会报错,具体见下图(xid=18、19我做了两次查询):
所以他的起始pos为:235,终止pos为:1441
6.查询完毕后退出数据库进入到mysql目录下准备恢复,命令: quit ; #cd /var/lib/mysql ;
mysql> quit
Bye
[root@atdajv ~]# cd /var/lib/mysql
[root@atdajv mysql]#
7.恢复数据,命令:
# /usr/bin/mysqlbinlog --start-position=235 --stop-position=1441 --database=databasename /var/lib/mysql/binlog.000004 | /usr/bin/mysql -uroot -ppassword -v databasename
效果如下:
.
.
.
SET @@SESSION.GTID_NEXT= 'AUTOMATIC'
--------------
--------------
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/
--------------
--------------
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/
--------------
[root@atdajv mysql]#
8.再次查询后数据已经恢复成功了
mysql> select * from reader;
+------+---------------+---------+--------------+
| rid | rName | lendNum | rAddress |
+------+---------------+---------+--------------+
| 001 | zhangYongwei | 2 | 北京西城 |
| 002 | zhangDawei | 1 | 北京东城 |
| 3 | jixiegongye | 10 | 北京南 |
| 4 | zhangchongkun | 10 | 北京北 |
| 5 | wangdaxian | 10 | 北京西 |
| 3 | jixiegongye | 10 | 北京南 |
| 4 | zhangchongkun | 10 | 北京北 |
| 5 | wangdaxian | 10 | 北京西 |
| 6 | liergou | 10 | 北京南 |
+------+---------------+---------+--------------+
9 rows in set (0.00 sec)
mysql>
9.收拾东西,不用跑路咯