MySQL用binlog日志恢复数据

原理:binlog日志保存的是数据变化的DDL和DML SQL,并在每条SQL打上了时间缀和标记,所以可以指定时间和标记,找到指定SQL,恢复特定数据。

实战:从删库到恢复,不用再跑路。

1、建库建表准备数据再删库

mysql> flush binary logs;
Query OK, 0 rows affected (0.01 sec)


mysql> create database mydb;
Query OK, 1 row affected (0.00 sec)


mysql> use mydb;
Database changed
mysql> create table t(id int);
Query OK, 0 rows affected (0.01 sec)


mysql> insert into t values(1);
Query OK, 1 row affected (0.00 sec)


mysql> insert into t values(2);
Query OK, 1 row affected (0.01 sec)


mysql> insert into t values(3);
Query OK, 1 row affected (0.00 sec)


mysql> select * from t;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)


mysql> drop database mydb;
Query OK, 1 row affected (0.05 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
8 rows in set (0.00 sec)

2、查看binlog日志记录

mysql> flush binary logs;
Query OK, 0 rows affected (0.01 sec)


mysql> show binary logs;
+---------------+-----------+-----------+
| Log_name      | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000001 |   3116922 | No        |
| binlog.000002 | 139255766 | No        |
| binlog.000003 |       157 | No        |
| binlog.000004 |       201 | No        |
| binlog.000005 |      1674 | No        |
| binlog.000006 |       492 | No        |
| binlog.000007 |      2196 | No        |
| binlog.000008 |       489 | No        |
| binlog.000009 |      2167 | No        |
| binlog.000010 |      1570 | No        |
| binlog.000011 |       157 | No        |
+---------------+-----------+-----------+
11 rows in set (0.00 sec)


mysql> show binlog events in 'binlog.000010';
+---------------+------+----------------+-----------+-------------+--------------------------------------------------+
| Log_name      | Pos  | Event_type     | Server_id | End_log_pos | Info                                             |
+---------------+------+----------------+-----------+-------------+--------------------------------------------------+
| binlog.000010 |    4 | Format_desc    |         1 |         126 | Server ver: 8.0.28, Binlog ver: 4                |
| binlog.000010 |  126 | Previous_gtids |         1 |         157 |                                                  |
| binlog.000010 |  157 | Anonymous_Gtid |         1 |         234 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'             |
| binlog.000010 |  234 | Query          |         1 |         342 | create database mydb /* xid=799 */               |
| binlog.000010 |  342 | Anonymous_Gtid |         1 |         419 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'             |
| binlog.000010 |  419 | Query          |         1 |         529 | use `mydb`; create table t(id int) /* xid=804 */ |
| binlog.000010 |  529 | Anonymous_Gtid |         1 |         608 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'             |
| binlog.000010 |  608 | Query          |         1 |         683 | BEGIN                                            |
| binlog.000010 |  683 | Table_map      |         1 |         730 | table_id: 99 (mydb.t)                            |
| binlog.000010 |  730 | Write_rows     |         1 |         770 | table_id: 99 flags: STMT_END_F                   |
| binlog.000010 |  770 | Xid            |         1 |         801 | COMMIT /* xid=805 */                             |
| binlog.000010 |  801 | Anonymous_Gtid |         1 |         880 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'             |
| binlog.000010 |  880 | Query          |         1 |         955 | BEGIN                                            |
| binlog.000010 |  955 | Table_map      |         1 |        1002 | table_id: 99 (mydb.t)                            |
| binlog.000010 | 1002 | Write_rows     |         1 |        1042 | table_id: 99 flags: STMT_END_F                   |
| binlog.000010 | 1042 | Xid            |         1 |        1073 | COMMIT /* xid=806 */                             |
| binlog.000010 | 1073 | Anonymous_Gtid |         1 |        1152 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'             |
| binlog.000010 | 1152 | Query          |         1 |        1227 | BEGIN                                            |
| binlog.000010 | 1227 | Table_map      |         1 |        1274 | table_id: 99 (mydb.t)                            |
| binlog.000010 | 1274 | Write_rows     |         1 |        1314 | table_id: 99 flags: STMT_END_F                   |
| binlog.000010 | 1314 | Xid            |         1 |        1345 | COMMIT /* xid=807 */                             |
| binlog.000010 | 1345 | Anonymous_Gtid |         1 |        1422 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'             |
| binlog.000010 | 1422 | Query          |         1 |        1526 | drop database mydb /* xid=809 */                 |
| binlog.000010 | 1526 | Rotate         |         1 |        1570 | binlog.000011;pos=4                              |
+---------------+------+----------------+-----------+-------------+--------------------------------------------------+
24 rows in set (0.00 sec)

1、看info列,找create database,位于第4行,其上一行为SET...设置SQL执行的环境变量,Pos为157,把它当作start-position;

2、看info列,先找drop database,再找其上方COMMIT,找到该行的End_log_pos 为1345,把它当作end-position;

 3、恢复数据,用上方找到start-position和end-position,筛选出所需binlog日志,再导入DB。

root@mysql:~# mysqlbinlog --start-position=157 --stop-position=1345 --database=mydb -v /var/lib/mysql/binlog.000010 > binlog_rec.txt
root@mysql:~# mysql -uroot -p123456 -v < binlog_rec.txt

4、检查恢复数据,数据库mydb恢复,表t恢复,数据恢复。

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
9 rows in set (0.00 sec)


mysql> use mydb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A


Database changed
mysql> show tables;
+----------------+
| Tables_in_mydb |
+----------------+
| t              |
+----------------+
1 row in set (0.00 sec)


mysql> select * from t;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

注意:如果binlog日志太大,mysql> show binary logs; 难以精确定位到Pos范围,使用mysqlbinlog联合grep一起查找,如下,Pos和End_log_pos为“# at”打头的行,同样能找到157和1345。

root@mysql:~# mysqlbinlog -v --base64-output='DECODE-ROWS' /var/lib/mysql/binlog.000010 | grep -C20 -i 'database'
#220325  6:19:27 server id 1  end_log_pos 157 CRC32 0x1ad148cc 	Previous-GTIDs
# [empty]
# at 157
#220325  6:20:07 server id 1  end_log_pos 234 CRC32 0xf6be5fed 	Anonymous_GTID	last_committed=0	sequence_number=1	rbr_only=no	original_committed_timestamp=1648189207588241	immediate_commit_timestamp=1648189207588241	transaction_length=185
# original_commit_timestamp=1648189207588241 (2022-03-25 06:20:07.588241 UTC)
# immediate_commit_timestamp=1648189207588241 (2022-03-25 06:20:07.588241 UTC)
/*!80001 SET @@session.original_commit_timestamp=1648189207588241*//*!*/;
/*!80014 SET @@session.original_server_version=80028*//*!*/;
/*!80014 SET @@session.immediate_server_version=80028*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 234
#220325  6:20:07 server id 1  end_log_pos 342 CRC32 0x4912f073 	Query	thread_id=8	exec_time=0	error_code=0	Xid = 799
SET TIMESTAMP=1648189207/*!*/;
SET @@session.pseudo_thread_id=8/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113696/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C latin1 *//*!*/;
SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=255/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
/*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/;
/*!80016 SET @@session.default_table_encryption=0*//*!*/;
create database mydb
/*!*/;
# at 342
#220325  6:20:30 server id 1  end_log_pos 419 CRC32 0x7a998c77 	Anonymous_GTID	last_committed=1	sequence_number=2	rbr_only=no	original_committed_timestamp=1648189230558417	immediate_commit_timestamp=1648189230558417	transaction_length=187
# original_commit_timestamp=1648189230558417 (2022-03-25 06:20:30.558417 UTC)
# immediate_commit_timestamp=1648189230558417 (2022-03-25 06:20:30.558417 UTC)
/*!80001 SET @@session.original_commit_timestamp=1648189230558417*//*!*/;
/*!80014 SET @@session.original_server_version=80028*//*!*/;
/*!80014 SET @@session.immediate_server_version=80028*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 419
#220325  6:20:30 server id 1  end_log_pos 529 CRC32 0x55eda454 	Query	thread_id=8	exec_time=0	error_code=0	Xid = 804
use `mydb`/*!*/;
SET TIMESTAMP=1648189230/*!*/;
/*!80013 SET @@session.sql_require_primary_key=0*//*!*/;
create table t(id int)
/*!*/;
# at 529
#220325  6:20:51 server id 1  end_log_pos 608 CRC32 0x63127526 	Anonymous_GTID	last_committed=2	sequence_number=3	rbr_only=yes	original_committed_timestamp=1648189251093346	immediate_commit_timestamp=1648189251093346	transaction_length=272
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
# original_commit_timestamp=1648189251093346 (2022-03-25 06:20:51.093346 UTC)
--
#220325  6:20:56 server id 1  end_log_pos 1274 CRC32 0x016cc72e 	Table_map: `mydb`.`t` mapped to number 99
# at 1274
#220325  6:20:56 server id 1  end_log_pos 1314 CRC32 0x4414727a 	Write_rows: table id 99 flags: STMT_END_F
### INSERT INTO `mydb`.`t`
### SET
###   @1=3
# at 1314
#220325  6:20:56 server id 1  end_log_pos 1345 CRC32 0xcf486367 	Xid = 807
COMMIT/*!*/;
# at 1345
#220325  6:21:25 server id 1  end_log_pos 1422 CRC32 0xc8959107 	Anonymous_GTID	last_committed=5	sequence_number=6	rbr_only=no	original_committed_timestamp=1648189285121605	immediate_commit_timestamp=1648189285121605	transaction_length=181
# original_commit_timestamp=1648189285121605 (2022-03-25 06:21:25.121605 UTC)
# immediate_commit_timestamp=1648189285121605 (2022-03-25 06:21:25.121605 UTC)
/*!80001 SET @@session.original_commit_timestamp=1648189285121605*//*!*/;
/*!80014 SET @@session.original_server_version=80028*//*!*/;
/*!80014 SET @@session.immediate_server_version=80028*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 1422
#220325  6:21:25 server id 1  end_log_pos 1526 CRC32 0xae1a52a4 	Query	thread_id=8	exec_time=0	error_code=0	Xid = 809
SET TIMESTAMP=1648189285/*!*/;
drop database mydb
/*!*/;
# at 1526
#220325  6:22:11 server id 1  end_log_pos 1570 CRC32 0xc0539b89 	Rotate to binlog.000011  pos: 4
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

你可能感兴趣的:(MySQL,mysql,数据库)