上一篇文章《MySQL日志之bin log》介绍了bin log
的基本概念和作用,接下来我们尝试使用bin log的数据恢复功能来恢复被误删的数据。
mysql> show variables like'%log_bin%';
+---------------------------------+----------------------------------------------------------------------+
| Variable_name | Value |
+---------------------------------+----------------------------------------------------------------------+
| log_bin | ON |
| log_bin_basename | C:\ProgramData\MySQL\MySQL Server 8.0\Data\SC-202010081028-bin |
| log_bin_index | C:\ProgramData\MySQL\MySQL Server 8.0\Data\SC-202010081028-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+----------------------------------------------------------------------+
之所以有这么多bin log
文件,是因为MySQL
服务重新启动一次 ,以“.000001”
为后缀的文件就会增加一个,并且后缀名按1递增。即日志文件的个数与MySQL
服务启动的次数相同。
查看当前的二进制日志文件列表及大小。指令如下:
mysql> SHOW BINARY LOGS;
+----------------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+----------------------------+-----------+-----------+
| SC-202010081028-bin.000582 | 179 | No |
| SC-202010081028-bin.000583 | 179 | No |
| SC-202010081028-bin.000584 | 156 | No |
| SC-202010081028-bin.000585 | 179 | No |
| SC-202010081028-bin.000586 | 179 | No |
| SC-202010081028-bin.000587 | 179 | No |
| SC-202010081028-bin.000588 | 179 | No |
| SC-202010081028-bin.000589 | 179 | No |
| SC-202010081028-bin.000590 | 179 | No |
| SC-202010081028-bin.000591 | 179 | No |
| SC-202010081028-bin.000592 | 179 | No |
| SC-202010081028-bin.000593 | 179 | No |
| SC-202010081028-bin.000594 | 179 | No |
| SC-202010081028-bin.000595 | 179 | No |
| SC-202010081028-bin.000596 | 179 | No |
| SC-202010081028-bin.000597 | 179 | No |
| SC-202010081028-bin.000598 | 179 | No |
| SC-202010081028-bin.000599 | 179 | No |
| SC-202010081028-bin.000600 | 179 | No |
| SC-202010081028-bin.000601 | 179 | No |
| SC-202010081028-bin.000602 | 179 | No |
| SC-202010081028-bin.000603 | 179 | No |
| SC-202010081028-bin.000604 | 179 | No |
| SC-202010081028-bin.000605 | 156 | No |
| SC-202010081028-bin.000606 | 179 | No |
| SC-202010081028-bin.000607 | 179 | No |
| SC-202010081028-bin.000608 | 179 | No |
| SC-202010081028-bin.000609 | 179 | No |
| SC-202010081028-bin.000610 | 179 | No |
| SC-202010081028-bin.000611 | 179 | No |
| SC-202010081028-bin.000612 | 179 | No |
| SC-202010081028-bin.000613 | 179 | No |
| SC-202010081028-bin.000614 | 179 | No |
| SC-202010081028-bin.000615 | 179 | No |
| SC-202010081028-bin.000616 | 179 | No |
| SC-202010081028-bin.000617 | 156 | No |
| SC-202010081028-bin.000618 | 179 | No |
| SC-202010081028-bin.000619 | 179 | No |
| SC-202010081028-bin.000620 | 179 | No |
| SC-202010081028-bin.000621 | 179 | No |
| SC-202010081028-bin.000622 | 179 | No |
| SC-202010081028-bin.000623 | 179 | No |
| SC-202010081028-bin.000624 | 179 | No |
| SC-202010081028-bin.000625 | 179 | No |
| SC-202010081028-bin.000626 | 179 | No |
| SC-202010081028-bin.000627 | 179 | No |
| SC-202010081028-bin.000628 | 179 | No |
| SC-202010081028-bin.000629 | 179 | No |
| SC-202010081028-bin.000630 | 179 | No |
| SC-202010081028-bin.000631 | 179 | No |
| SC-202010081028-bin.000632 | 179 | No |
| SC-202010081028-bin.000633 | 179 | No |
| SC-202010081028-bin.000634 | 179 | No |
| SC-202010081028-bin.000635 | 179 | No |
| SC-202010081028-bin.000636 | 179 | No |
| SC-202010081028-bin.000637 | 156 | No |
| SC-202010081028-bin.000638 | 1319 | No |
+----------------------------+-----------+-----------+
57 rows in set (0.06 sec)
下面命令行工具将行事件以伪SQL
的形式表现出来(注意不是mysql
命令行,当前路径的文件直接用文件名,绝对路的文件名要加双引号)
mysqlbinlog -v binlog文件名
mysql> select * from test1;
+---+---+---+
| a | b | c |
+---+---+---+
| 2 | 2 | 4 |
+---+---+---+
1 row in set (0.03 sec)
mysql>
mysql> insert into test1(a,b)values(4,5);
Query OK, 1 row affected (0.01 sec)
mysql> select * from test1;
+---+---+---+
| a | b | c |
+---+---+---+
| 2 | 2 | 4 |
| 4 | 5 | 9 |
+---+---+---+
2 rows in set (0.03 sec)
C:\ProgramData\MySQL\MySQL Server 8.0\Data>mysqlbinlog -v SC-202010081028-bin.000638
# The proper term is pseudo_replica_mode, but we use this compatibility alias
# to make the statement usable on server versions 8.0.24 and older.
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#230629 8:34:21 server id 1 end_log_pos 125 CRC32 0xa0c003ee Start: binlog v 4, server v 8.0.26 created 230629 8:34:21 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
jdGcZA8BAAAAeQAAAH0AAAABAAQAOC4wLjI2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACN0ZxkEwANAAgAAAAABAAEAAAAYQAEGggAAAAICAgCAAAACgoKKioAEjQA
CigB7gPAoA==
'/*!*/;
# at 125
#230629 8:34:21 server id 1 end_log_pos 156 CRC32 0x9311412b Previous-GTIDs
# [empty]
# at 156
#230629 14:46:55 server id 1 end_log_pos 235 CRC32 0x005df31b Anonymous_GTID last_committed=0 sequence_number=1 rbr_only=yes original_committed_timestamp=1688021215055701 immediate_commit_timestamp=1688021215055701
transaction_length=288
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
# original_commit_timestamp=1688021215055701 (2023-06-29 14:46:55.055701 中国标准时间)
# immediate_commit_timestamp=1688021215055701 (2023-06-29 14:46:55.055701 中国标准时间)
/*!80001 SET @@session.original_commit_timestamp=1688021215055701*//*!*/;
/*!80014 SET @@session.original_server_version=80026*//*!*/;
/*!80014 SET @@session.immediate_server_version=80026*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 235
#230629 14:46:55 server id 1 end_log_pos 311 CRC32 0x8526ecac Query thread_id=8 exec_time=0 error_code=0
SET TIMESTAMP=1688021215/*!*/;
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=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=255/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
/*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/;
BEGIN
/*!*/;
# at 311
#230629 14:46:55 server id 1 end_log_pos 365 CRC32 0x3fb65eaa Table_map: `test1`.`test1` mapped to number 95
# at 365
#230629 14:46:55 server id 1 end_log_pos 413 CRC32 0x871cd084 Write_rows: table id 95 flags: STMT_END_F
BINLOG '
3yidZBMBAAAANgAAAG0BAAAAAF8AAAAAAAEABXRlc3QxAAV0ZXN0MQADAwMDAAcBAQCqXrY/
3yidZB4BAAAAMAAAAJ0BAAAAAF8AAAAAAAEAAgAD/wAEAAAABQAAAAkAAACE0ByH
'/*!*/;
### INSERT INTO `test1`.`test1`
### SET
### @1=4
### @2=5
### @3=9
# at 413
#230629 14:46:55 server id 1 end_log_pos 444 CRC32 0x8bb47538 Xid = 61
COMMIT/*!*/;
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*/;
注意要找到新增记录的pos
点信息。
mysql> insert into test1(a,b)values(6,7);
Query OK, 1 row affected (0.01 sec)
mysql> select * from test1;
+---+---+----+
| a | b | c |
+---+---+----+
| 2 | 2 | 4 |
| 4 | 5 | 9 |
| 6 | 7 | 13 |
+---+---+----+
3 rows in set (0.03 sec)
C:\ProgramData\MySQL\MySQL Server 8.0\Data>mysqlbinlog -v SC-202010081028-bin.000638
### 过滤掉其他信息
#230629 14:47:56 server id 1 end_log_pos 701 CRC32 0x98b71e46 Write_rows: table id 95 flags: STMT_END_F
BINLOG '
HCmdZBMBAAAANgAAAI0CAAAAAF8AAAAAAAEABXRlc3QxAAV0ZXN0MQADAwMDAAcBAQBtX3Kh
HCmdZB4BAAAAMAAAAL0CAAAAAF8AAAAAAAEAAgAD/wAGAAAABwAAAA0AAABGHreY
'/*!*/;
### INSERT INTO `test1`.`test1`
### SET
### @1=6
### @2=7
### @3=13
# at 701
#230629 14:47:56 server id 1 end_log_pos 732 CRC32 0x2940622a Xid = 65
COMMIT/*!*/;
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> delete from test1 where a = 4;
Query OK, 1 row affected (0.00 sec)
mysql> select * from test1;
+---+---+----+
| a | b | c |
+---+---+----+
| 2 | 2 | 4 |
| 6 | 7 | 13 |
+---+---+----+
2 rows in set (0.03 sec)
C:\ProgramData\MySQL\MySQL Server 8.0\Data>mysqlbinlog -v SC-202010081028-bin.000638
### 过滤掉其他信息
#230629 15:00:51 server id 1 end_log_pos 887 CRC32 0x4205f3d5 Query thread_id=8 exec_time=0 error_code=0
SET TIMESTAMP=1688022051/*!*/;
BEGIN
/*!*/;
# at 887
#230629 15:00:51 server id 1 end_log_pos 941 CRC32 0x8d7fe6a2 Table_map: `test1`.`test1` mapped to number 95
# at 941
#230629 15:00:51 server id 1 end_log_pos 989 CRC32 0x32e8e1b9 Delete_rows: table id 95 flags: STMT_END_F
### DELETE FROM `test1`.`test1`
### WHERE
### @1=4
### @2=5
### @3=9
# at 989
#230629 15:00:51 server id 1 end_log_pos 1020 CRC32 0x82bb9037 Xid = 69
COMMIT/*!*/;
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*/;
上面这种办法读取出
binlog
日志的全文内容比较多,不容易分辨查看到pos
点信息,下面介绍一种更为方便的查询命令
mysql> show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];
IN 'log_name'
:指定要查询的binlog
文件名(不指定就是第一个binlog
文件)FROM pos
:指定从哪个pos
起始点开始查起(不指定就是从整个文件首个pos
点开始算)LIMIT [offset]
:偏移量(不指定就是0)row_count
:查询总条数(不指定就是所有行)注意需要在MySQL
命令行中执行该命令:
mysql> show binlog events in 'SC-202010081028-bin.000638';
+----------------------------+-----+----------------+-----------+-------------+--------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+----------------------------+-----+----------------+-----------+-------------+--------------------------------------+
| SC-202010081028-bin.000638 | 4 | Format_desc | 1 | 125 | Server ver: 8.0.26, Binlog ver: 4 |
| SC-202010081028-bin.000638 | 125 | Previous_gtids | 1 | 156 | |
| SC-202010081028-bin.000638 | 156 | Anonymous_Gtid | 1 | 235 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| SC-202010081028-bin.000638 | 235 | Query | 1 | 311 | BEGIN |
| SC-202010081028-bin.000638 | 311 | Table_map | 1 | 365 | table_id: 95 (test1.test1) |
| SC-202010081028-bin.000638 | 365 | Write_rows | 1 | 413 | table_id: 95 flags: STMT_END_F |
| SC-202010081028-bin.000638 | 413 | Xid | 1 | 444 | COMMIT /* xid=61 */ |
| SC-202010081028-bin.000638 | 444 | Anonymous_Gtid | 1 | 523 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| SC-202010081028-bin.000638 | 523 | Query | 1 | 599 | BEGIN |
| SC-202010081028-bin.000638 | 599 | Table_map | 1 | 653 | table_id: 95 (test1.test1) |
| SC-202010081028-bin.000638 | 653 | Write_rows | 1 | 701 | table_id: 95 flags: STMT_END_F |
| SC-202010081028-bin.000638 | 701 | Xid | 1 | 732 | COMMIT /* xid=65 */ |
| SC-202010081028-bin.000638 | 732 | Anonymous_Gtid | 1 | 811 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| SC-202010081028-bin.000638 | 811 | Query | 1 | 887 | BEGIN |
| SC-202010081028-bin.000638 | 887 | Table_map | 1 | 941 | table_id: 95 (test1.test1) |
| SC-202010081028-bin.000638 | 941 | Delete_rows | 1 | 989 | table_id: 95 flags: STMT_END_F |
| SC-202010081028-bin.000638 | 989 | Xid | 1 | 1020 | COMMIT /* xid=69 */ |
+----------------------------+-----+----------------+-----------+-------------+--------------------------------------+
17 rows in set (0.05 sec)
使用
mysqlbinlog
命令来读取filename
中的内容,然后使用mysql
命令将这些内容恢复到数据库中。
mysqlbinlog [option] filename|mysql –u user -p password;
filename
:是日志文件名。
option
:可选项,比较重要的两对option
参数是--start-date
、--stop-date
和 --start-position、--stop-position
。
--start-date
和 --stop-date :可以指定恢复数据库的起始时间点和结束时间点。
--start-position
和--stop-position
:可以指定恢复数据的开始位置和结束位置。
示例如下:
>mysqlbinlog --start-position=219 --stop-position=636 --database=mall_local "C:\DevTools\mysql-5.7\data\mysql-bin.000012" |mysql -uroot -proot -v mall_local
>mysqlbinlog --start-datetime="2022-01-05 15:39:22" --stop-datetime="2022-01-05 15:40:19l" --database=mall_local "C:\DevTools\mysql-5.7\data\mysql-bin.000012" | /usr/bin/mysql -uroot -proot -v mall_local
下面以--start-position
格式恢复被删的数据,这里我们想恢复到a=4
的记录:
执行恢复命令
C:\ProgramData\MySQL\MySQL Server 8.0\Data>mysqlbinlog --start-position=235 --stop-position=444 --database=test1 "C:\ProgramData\MySQL\MySQL Server 8.0\Data\SC-202010081028-bin.000638" |mysql -uroot -proot123 -v test1
mysql: [Warning] Using a password on the command line interface can be insecure.
--------------
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/
--------------
--------------
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/
--------------
--------------
ROLLBACK
--------------
--------------
BINLOG '
jdGcZA8BAAAAeQAAAH0AAAABAAQAOC4wLjI2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACN0ZxkEwANAAgAAAAABAAEAAAAYQAEGggAAAAICAgCAAAACgoKKioAEjQA
CigB7gPAoA==
'
--------------
--------------
SET TIMESTAMP=1688021215
--------------
--------------
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=1075838976
--------------
--------------
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1
--------------
--------------
/*!*/
--------------
--------------
SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=255
--------------
--------------
SET @@session.lc_time_names=0
--------------
--------------
SET @@session.collation_database=DEFAULT
--------------
--------------
/*!80011 SET @@session.default_collation_for_utf8mb4=255*/
--------------
--------------
BEGIN
--------------
--------------
BINLOG '
3yidZBMBAAAANgAAAG0BAAAAAF8AAAAAAAEABXRlc3QxAAV0ZXN0MQADAwMDAAcBAQCqXrY/
3yidZB4BAAAAMAAAAJ0BAAAAAF8AAAAAAAEAAgAD/wAEAAAABQAAAAkAAACE0ByH
'
--------------
--------------
COMMIT
--------------
--------------
SET @@SESSION.GTID_NEXT= 'AUTOMATIC'
--------------
--------------
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/
--------------
--------------
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/
--------------
执行成功后查看数据是否恢复
mysql> select * from test1;
+---+---+----+
| a | b | c |
+---+---+----+
| 2 | 2 | 4 |
| 6 | 7 | 13 |
| 4 | 5 | 9 |
+---+---+----+
3 rows in set (0.03 sec)
查看bin log
mysql> show binlog events in 'SC-202010081028-bin.000638';
+----------------------------+------+----------------+-----------+-------------+--------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+----------------------------+------+----------------+-----------+-------------+--------------------------------------+
| SC-202010081028-bin.000638 | 4 | Format_desc | 1 | 125 | Server ver: 8.0.26, Binlog ver: 4 |
| SC-202010081028-bin.000638 | 125 | Previous_gtids | 1 | 156 | |
| SC-202010081028-bin.000638 | 156 | Anonymous_Gtid | 1 | 235 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| SC-202010081028-bin.000638 | 235 | Query | 1 | 311 | BEGIN |
| SC-202010081028-bin.000638 | 311 | Table_map | 1 | 365 | table_id: 95 (test1.test1) |
| SC-202010081028-bin.000638 | 365 | Write_rows | 1 | 413 | table_id: 95 flags: STMT_END_F |
| SC-202010081028-bin.000638 | 413 | Xid | 1 | 444 | COMMIT /* xid=61 */ |
| SC-202010081028-bin.000638 | 444 | Anonymous_Gtid | 1 | 523 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| SC-202010081028-bin.000638 | 523 | Query | 1 | 599 | BEGIN |
| SC-202010081028-bin.000638 | 599 | Table_map | 1 | 653 | table_id: 95 (test1.test1) |
| SC-202010081028-bin.000638 | 653 | Write_rows | 1 | 701 | table_id: 95 flags: STMT_END_F |
| SC-202010081028-bin.000638 | 701 | Xid | 1 | 732 | COMMIT /* xid=65 */ |
| SC-202010081028-bin.000638 | 732 | Anonymous_Gtid | 1 | 811 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| SC-202010081028-bin.000638 | 811 | Query | 1 | 887 | BEGIN |
| SC-202010081028-bin.000638 | 887 | Table_map | 1 | 941 | table_id: 95 (test1.test1) |
| SC-202010081028-bin.000638 | 941 | Delete_rows | 1 | 989 | table_id: 95 flags: STMT_END_F |
| SC-202010081028-bin.000638 | 989 | Xid | 1 | 1020 | COMMIT /* xid=69 */ |
| SC-202010081028-bin.000638 | 1020 | Anonymous_Gtid | 1 | 1110 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| SC-202010081028-bin.000638 | 1110 | Query | 1 | 1186 | BEGIN |
| SC-202010081028-bin.000638 | 1186 | Table_map | 1 | 1240 | table_id: 95 (test1.test1) |
| SC-202010081028-bin.000638 | 1240 | Write_rows | 1 | 1288 | table_id: 95 flags: STMT_END_F |
| SC-202010081028-bin.000638 | 1288 | Xid | 1 | 1319 | COMMIT /* xid=180 */ |
+----------------------------+------+----------------+-----------+-------------+--------------------------------------+
22 rows in set (0.05 sec)
10081028-bin.000638 | 1186 | Table_map | 1 | 1240 | table_id: 95 (test1.test1) |
| SC-202010081028-bin.000638 | 1240 | Write_rows | 1 | 1288 | table_id: 95 flags: STMT_END_F |
| SC-202010081028-bin.000638 | 1288 | Xid | 1 | 1319 | COMMIT /* xid=180 */ |
±---------------------------±-----±---------------±----------±------------±-------------------------------------+
22 rows in set (0.05 sec)