同事上线,把数据库初始化脚本改了名。结果导致上线把库表的数据全给重新初始化了。这下事来了,恢复库表。
之前用过阿里云的库表恢复,非常简洁,那这次也照猫画虎学一回,步骤如下:
一、保存现在的记录:
把所有相关的binlog拷贝到一个备份目录保存。
二、最好新建一个mysql实例:
阿里确实事新起了一个实例,避免操作对旧实例造成影响。
我们实战中可能没必要,但也要封锁数据库的读写:
iptables -I INPUT -p tcp --dport 3306 -j DROP
# 把自己放通,后续可能自己要进行 mysql 或 mysqldump 的操作
iptables -I INPUT -s 127.0.0.1/32 -p tcp --dport 12530 -j ACCEPT
三、解析binlog
我们需要把重放日志拿出来:
mysqlbinlog --start-datetime="2025-01-02 14:40:00" --stop-datetime="2025-01-02 14:50:00" --verbose binlog.000009 |grep -i -C15 "drop table"|more
mysqlbinlog binlog.000009 --stop-position=260734003 --database=work_oa > 9.sql
注意,分析:看到 at 260734003 下面有个 drop table ,说明是在 260734003 之后发生了 drop table 操作
所以,回放到260734003就可以了。之后、之后、之后才操作的!!!
/*!80014 SET @@session.original_server_version=80019*//*!*/;
/*!80014 SET @@session.immediate_server_version=80019*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 260734003
#200311 20:06:20 server id 1 end_log_pos 355 CRC32 0x2fc1e5ea Query thread_id=16 exec_time=0 error_code=0
SET TIMESTAMP=1583971580/*!*/;
SET @@session.pseudo_thread_id=16/*!*/;
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 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*//*!*/;
DROP TABLE `pets`.`cats` /* generated by server */
/*!*/;
# at 260734009
#200311 20:07:48 server id 1 end_log_pos 434 CRC32 0x123d65df Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=no original_committed_timestamp=1583971668462467 immediate_commit_timestamp=1583971668462467 transaction_length=473
# original_commit_timestamp=1583971668462467 (2020-03-11 20:07:48.462467 EDT)
# immediate_commit_timestamp=1583971668462467 (2020-03-11 20:07:48.462467 EDT)
/*!80001 SET @@session.original_commit_timestamp=1583971668462467*//*!*/;
/*!80014 SET @@session.original_server_version=80019*//*!*/;
/*!80014 SET @@session.immediate_server_version=80019*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 260734188
#200311 20:07:48 server id 1 end_log_pos 828 CRC32 0x57fac9ac Query thread_id=16 exec_time=0 error_code=0 Xid = 217
use `pets`/*!*/;
SET TIMESTAMP=1583971668/*!*/;
/*!80013 SET @@session.sql_require_primary_key=0*//*!*/;
CREATE TABLE dogs
我们还是先找到 binlog 中 drop table 之类的操作字样,然后确定 position 后,把 binlog.00009 中之前的 log 导出。
别忘记了, 前面还有8个binlog
mysqlbinlog -d work_oa binlog.000001 > 1.sql
mysqlbinlog -d work_oa binlog.000002 > 2.sql
mysqlbinlog -d work_oa binlog.000003 > 3.sql
mysqlbinlog -d work_oa binlog.000004 > 4.sql
mysqlbinlog -d work_oa binlog.000005 > 5.sql
mysqlbinlog -d work_oa binlog.000006 > 6.sql
mysqlbinlog -d work_oa binlog.000007 > 7.sql
mysqlbinlog -d work_oa binlog.000008 > 8.sql
然后还要看 *.sql 的大小,发现都是1.7G,1.6G
四、恢复
注意上一节关注的文件大小。我们需要修改2个地方:
1、服务器,binlog导出的文件,导入服务器的时候数据包会非常大,所以1.7G文件,最好放大到2G
cat /etc/my.cnf
[mysqld]
max_allowed_packet=2048M
2、客户端导入
# 因为是直接在老库上操作,所以必须先干掉库
drop database work_oa
# 恢复
mysql --max_allowed_packet=100M -u root -p work_oa < 1.sql
mysql --max_allowed_packet=100M -u root -p work_oa < 2.sql
mysql --max_allowed_packet=100M -u root -p work_oa < 3.sql
mysql --max_allowed_packet=100M -u root -p work_oa < 4.sql
mysql --max_allowed_packet=100M -u root -p work_oa < 5.sql
mysql --max_allowed_packet=100M -u root -p work_oa < 6.sql
mysql --max_allowed_packet=100M -u root -p work_oa < 7.sql
mysql --max_allowed_packet=100M -u root -p work_oa < 8.sql
mysql --max_allowed_packet=100M -u root -p work_oa < 9.sql
这样就恢复完了。如果是在阿里云,那就是恢复到了一个新实例的新库里,然后在把库表导出,再导入到老库中,就是一个完美的恢复了。
善后事宜:
一定要做个full backup:
mysqldump -uroot -p -h 127.0.0.1 -P3306 --opt --triggers -R --hex-blob --single-transaction --flush-logs --master-data=2 --all-databases > all-20250103.sql
做完后查看 all-20250103.sql

说明这个备份是从 binlog.000031 开始的,之前的都可以不要了,so,删除之前的,只保留000031之后的:
PURGE BINARY LOGS TO 'binlog.000031';