MySQL通过binlog恢复数据

MySQL通过binlog恢复数据

一、背景

在MySQL中,如果不小心删除了数据,可以利用二进制日志(binlog)来恢复数据。

  • 实质就是将binlog记录中的事件再次执行一遍。

二、前提条件

  1. 启用二进制日志:确保 MySQL 启用了二进制日志功能。
  2. 有足够的权限:确保有权限访问和读取二进制日志文件。

三、恢复步骤

  1. 找到相关的二进制日志文件:

    bash 复制代码
    查看是否开启二进制日志文件
    SHOW VARIABLES LIKE 'log_bin%';
    
    查看二进制日志文件位置
    SHOW VARIABLES LIKE 'log_bin_basename';
    
    查看二进制日志文件列表
    SHOW BINARY LOGS;
  2. 使用 mysqlbinlog 工具提取日志 :事件位置

    • 先使用show binlog events命令查看binlog记录,确定事件开始位置和结束位置。

      sql 复制代码
      查看二进制日志记录
      show binlog events in 'binlog.00001';
    • 再使用 mysqlbinlog 提取开始位置和结束位置的日志:

      bash 复制代码
      mysqlbinlog /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 为数据库名称。
  3. 使用 mysqlbinlog 工具提取日志 :时间段

    • 使用 mysqlbinlog 提取特定时间段的日志:

      bash 复制代码
      mysqlbinlog /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.插入数据

  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
  2. 插入两条数据

    sql 复制代码
    mysql> 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恢复删除的数据

  1. 找到二进制日志文件:/usr/local/mysql/data/binlog.000002

    sql 复制代码
    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)
  2. 查看二进制日志记录,确认事件开始位置(13508)和结束位置(14142)

    sql 复制代码
    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 */               
  3. 使用 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 
相关推荐
kobe_OKOK_5 小时前
mysql 开启 binlog 日志
数据库·mysql
鸽芷咕5 小时前
KingbaseES 调参先看执行计划,参数是答案不是起点
数据库
这个DBA有点耶6 小时前
MySQL 8.0直方图:统计信息升级了,执行计划为什么还是选错?
数据库·mysql·代码规范
老纪的技术唠嗑局7 小时前
把 seekdb 塞进 iOS App:让混合检索嵌入手机
数据库
ClouGence8 小时前
开源数据库管理工具 CloudDM 新版本发布,支持 OpenSearch、IoTDB 数据源
数据库·开源
徐小黑ACG9 小时前
Redis-基础
数据库·redis·缓存
火山引擎开发者社区9 小时前
案例实践 | 让 Agent 读懂业务口径:ContextSearch 在广告数据查询中的实践
数据库
10年前端老司机10 小时前
Milvus 8种检索能力实践
数据库·python·agent
aiks_yuan10 小时前
MySQL 深分页 LIMIT 越翻越慢怎么办:300 万行实测 OFFSET、延迟关联和 keyset 的耗时差距(MySQL 8.2)
mysql
Decay__10 小时前
14_MySQL 高可用与容灾架构 —— MGR / InnoDB Cluster / Keepalived+VIP / 双主 / 读写分离 / 两地三中心
运维·数据库·sql·mysql·架构