MySQL通过binlog恢复数据
一、背景
在MySQL中,如果不小心删除了数据,可以利用二进制日志(binlog
)来恢复数据。
- 实质就是将
binlog
记录中的事件再次执行一遍。
二、前提条件
- 启用二进制日志:确保 MySQL 启用了二进制日志功能。
- 有足够的权限:确保有权限访问和读取二进制日志文件。
三、恢复步骤
-
找到相关的二进制日志文件:
bash查看是否开启二进制日志文件 SHOW VARIABLES LIKE 'log_bin%'; 查看二进制日志文件位置 SHOW VARIABLES LIKE 'log_bin_basename'; 查看二进制日志文件列表 SHOW BINARY LOGS;
-
使用
mysqlbinlog
工具提取日志 :事件位置-
先使用
show binlog events
命令查看binlog
记录,确定事件开始位置和结束位置。sql查看二进制日志记录 show binlog events in 'binlog.00001';
-
再使用
mysqlbinlog
提取开始位置和结束位置的日志:bashmysqlbinlog /path/to/binlog.000001 --start-position=13508 --stop-position=14142 | mysql -u username -p database_name
- 替换
/path/to/binlog.000001
为二进制日志文件路径 - 修改
stop-position
和stop-position
- 替换
username
为MySQL 用户名 ,database_name
为数据库名称。
- 替换
-
-
使用
mysqlbinlog
工具提取日志 :时间段-
使用
mysqlbinlog
提取特定时间段的日志:bashmysqlbinlog /path/to/binlog.000001 --start-datetime="YYYY-MM-DD HH:MM:SS" --stop-datetime="YYYY-MM-DD HH:MM:SS" | mysql -u username -p database_name
- 替换
/path/to/binlog.000001
为二进制日志文件路径 - 修改
start-datetime
和stop-datetime
- 替换
username
为MySQL 用户名 ,database_name
为数据库名称。
- 替换
-
注意事项
- 备份当前数据:在进行数据恢复操作之前,最好先备份当前数据库,以防止进一步的数据丢失。
- 测试恢复脚本:在生产环境中执行恢复脚本之前,可以先在测试环境中进行测试,确保恢复操作的正确性。
mysqlbinlog
命令只用于恢复,不能用于回滚。适用数据迁移,数据同步的场景。
四、实操
1.插入数据
-
mysql -u root -p
登陆sql➜ ~ mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \\g. Your MySQL connection id is 40 Server version: 8.4.3 MySQL Community Server - GPL
-
插入两条数据
sqlmysql> use ban; mysql> INSERT INTO t_user (id, name, phone) VALUES ('1', '小明', '110'); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO t_user (id, name, phone) VALUES ('2', '小红', '120'); Query OK, 1 row affected (0.00 sec) mysql> select * from t_user; +----+--------+-------+---------------------+---------------------+ | id | name | phone | create_dt | update_dt | +----+--------+-------+---------------------+---------------------+ | 1 | 小明 | 110 | 2025-01-24 15:19:39 | 2025-01-24 15:19:39 | | 2 | 小红 | 120 | 2025-01-24 15:19:46 | 2025-01-24 15:19:46 | +----+--------+-------+---------------------+---------------------+ 2 rows in set (0.00 sec)
2.删除数据
sql
mysql> delete from t_user where id in(1,2);
Query OK, 2 rows affected (0.00 sec)
mysql> select * from t_user;
Empty set (0.00 sec)
3.通过binlog
恢复删除的数据
-
找到二进制日志文件:
/usr/local/mysql/data/binlog.000002
sqlmysql> SHOW VARIABLES LIKE 'log_bin_basename'; +------------------+------------------------------+ | Variable_name | Value | +------------------+------------------------------+ | log_bin_basename | /usr/local/mysql/data/binlog | +------------------+------------------------------+ 1 row in set (0.01 sec) mysql> SHOW BINARY LOGS; +---------------+-----------+-----------+ | Log_name | File_size | Encrypted | +---------------+-----------+-----------+ | binlog.000001 | 668 | No | | binlog.000002 | 14142 | No | | binlog.000003 | 181 | No | | binlog.000004 | 181 | No | | binlog.000005 | 181 | No | +---------------+-----------+-----------+ 5 rows in set (0.01 sec)
-
查看二进制日志记录,确认事件开始位置(13508)和结束位置(14142)
sqlmysql> show binlog events in 'binlog.00002'; | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | binlog.00002 | 13508 | Anonymous_Gtid | 1 | 13587 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | binlog.00002 | 13587 | Query | 1 | 13669 | BEGIN | binlog.00002 | 13669 | Table_map | 1 | 13734 | table_id: 109 (ban.t_user) | binlog.00002 | 13734 | Write_rows | 1 | 13794 | table_id: 109 flags: STMT_END_F | binlog.00002 | 13794 | Xid | 1 | 13825 | COMMIT /* xid=1058 */ | binlog.00002 | 13825 | Anonymous_Gtid | 1 | 13904 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | binlog.00002 | 13904 | Query | 1 | 13986 | BEGIN | binlog.00002 | 13986 | Table_map | 1 | 14051 | table_id: 109 (ban.t_user) | binlog.00002 | 14051 | Write_rows | 1 | 14111 | table_id: 109 flags: STMT_END_F | binlog.00002 | 14111 | Xid | 1 | 14142 | COMMIT /* xid=1059 */
-
使用
mysqlbinlog
恢复数据bash➜ ~ mysqlbinlog /usr/local/mysql/data/binlog.00002 --start-position=13508 --stop-position=14142 | mysql -u root -p ban
4.完整示例
sql
登陆
➜ ~ mysql -u root -p
Enter password:
插入数据
mysql> use ban;
mysql> INSERT INTO t_user (id, name, phone) VALUES ('1', '小明', '110');
mysql> INSERT INTO t_user (id, name, phone) VALUES ('2', '小红', '120');
mysql> select * from t_user;
+----+--------+-------+---------------------+---------------------+
| id | name | phone | create_dt | update_dt |
+----+--------+-------+---------------------+---------------------+
| 1 | 小明 | 110 | 2025-01-24 15:19:39 | 2025-01-24 15:19:39 |
| 2 | 小红 | 120 | 2025-01-24 15:19:46 | 2025-01-24 15:19:46 |
+----+--------+-------+---------------------+---------------------+
2 rows in set (0.00 sec)
删除数据
mysql> delete from t_user where id in(1,2);
mysql> select * from t_user;
Empty set (0.00 sec)
通过binlog恢复删除的数据
找到二进制日志文件:/usr/local/mysql/data/binlog.000002
mysql> SHOW VARIABLES LIKE 'log_bin_basename';
+------------------+------------------------------+
| Variable_name | Value |
+------------------+------------------------------+
| log_bin_basename | /usr/local/mysql/data/binlog |
+------------------+------------------------------+
1 row in set (0.01 sec)
mysql> SHOW BINARY LOGS;
+---------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000001 | 668 | No |
| binlog.000002 | 14142 | No |
| binlog.000003 | 181 | No |
| binlog.000004 | 181 | No |
| binlog.000005 | 181 | No |
+---------------+-----------+-----------+
5 rows in set (0.01 sec)
查看二进制日志记录,确认事件开始位置(13508)和结束位置(14142)
mysql> show binlog events in 'binlog.00002';
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info
| binlog.00002 | 13508 | Anonymous_Gtid | 1 | 13587 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
| binlog.00002 | 13587 | Query | 1 | 13669 | BEGIN
| binlog.00002 | 13669 | Table_map | 1 | 13734 | table_id: 109 (ban.t_user)
| binlog.00002 | 13734 | Write_rows | 1 | 13794 | table_id: 109 flags: STMT_END_F
| binlog.00002 | 13794 | Xid | 1 | 13825 | COMMIT /* xid=1058 */
| binlog.00002 | 13825 | Anonymous_Gtid | 1 | 13904 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
| binlog.00002 | 13904 | Query | 1 | 13986 | BEGIN
| binlog.00002 | 13986 | Table_map | 1 | 14051 | table_id: 109 (ban.t_user)
| binlog.00002 | 14051 | Write_rows | 1 | 14111 | table_id: 109 flags: STMT_END_F
| binlog.00002 | 14111 | Xid | 1 | 14142 | COMMIT /* xid=1059 */
使用 mysqlbinlog 恢复数据
➜ ~ mysqlbinlog /usr/local/mysql/data/binlog.00002 --start-position=13508 --stop-position=14142 | mysql -u root -p ban