同事上线,把数据库初始化脚本改了名。结果导致上线把库表的数据全给重新初始化了。这下事来了,恢复库表。
之前用过阿里云的库表恢复,非常简洁,那这次也照猫画虎学一回,步骤如下:
一、保存现在的记录:
把所有相关的binlog拷贝到一个备份目录保存。
二、最好新建一个mysql实例:
阿里确实事新起了一个实例,避免操作对旧实例造成影响。
我们实战中可能没必要,但也要封锁数据库的读写:
1iptables -I INPUT -p tcp --dport 3306 -j DROP
2
3# 把自己放通,后续可能自己要进行 mysql 或 mysqldump 的操作
4iptables -I INPUT -s 127.0.0.1/32 -p tcp --dport 12530 -j ACCEPT
三、解析binlog
我们需要把重放日志拿出来:
1mysqlbinlog --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
2
3mysqlbinlog binlog.000009 --stop-position=260734003 --database=work_oa > 9.sql
1注意,分析:看到 at 260734003 下面有个 drop table ,说明是在 260734003 之后发生了 drop table 操作
2所以,回放到260734003就可以了。之后、之后、之后才操作的!!!
3
4/*!80014 SET @@session.original_server_version=80019*//*!*/;
5/*!80014 SET @@session.immediate_server_version=80019*//*!*/;
6SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
7# at 260734003
8#200311 20:06:20 server id 1 end_log_pos 355 CRC32 0x2fc1e5ea Query thread_id=16 exec_time=0 error_code=0
9SET TIMESTAMP=1583971580/*!*/;
10SET @@session.pseudo_thread_id=16/*!*/;
11SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
12SET @@session.sql_mode=1168113696/*!*/;
13SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
14/*!\C utf8mb4 *//*!*/;
15SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=255/*!*/;
16SET @@session.lc_time_names=0/*!*/;
17SET @@session.collation_database=DEFAULT/*!*/;
18/*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/;
19DROP TABLE `pets`.`cats` /* generated by server */
20/*!*/;
21# at 260734009
22#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
23# original_commit_timestamp=1583971668462467 (2020-03-11 20:07:48.462467 EDT)
24# immediate_commit_timestamp=1583971668462467 (2020-03-11 20:07:48.462467 EDT)
25/*!80001 SET @@session.original_commit_timestamp=1583971668462467*//*!*/;
26/*!80014 SET @@session.original_server_version=80019*//*!*/;
27/*!80014 SET @@session.immediate_server_version=80019*//*!*/;
28SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
29# at 260734188
30#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
31use `pets`/*!*/;
32SET TIMESTAMP=1583971668/*!*/;
33/*!80013 SET @@session.sql_require_primary_key=0*//*!*/;
34CREATE TABLE dogs
我们还是先找到 binlog 中 drop table 之类的操作字样,然后确定 position 后,把 binlog.00009 中之前的 log 导出。
别忘记了, 前面还有8个binlog
1mysqlbinlog -d work_oa binlog.000001 > 1.sql
2mysqlbinlog -d work_oa binlog.000002 > 2.sql
3mysqlbinlog -d work_oa binlog.000003 > 3.sql
4mysqlbinlog -d work_oa binlog.000004 > 4.sql
5mysqlbinlog -d work_oa binlog.000005 > 5.sql
6mysqlbinlog -d work_oa binlog.000006 > 6.sql
7mysqlbinlog -d work_oa binlog.000007 > 7.sql
8mysqlbinlog -d work_oa binlog.000008 > 8.sql
然后还要看 *.sql 的大小,发现都是1.7G,1.6G
四、恢复
注意上一节关注的文件大小。我们需要修改2个地方:
1、服务器,binlog导出的文件,导入服务器的时候数据包会非常大,所以1.7G文件,最好放大到2G
1cat /etc/my.cnf
2[mysqld]
3max_allowed_packet=2048M
2、客户端导入
1# 因为是直接在老库上操作,所以必须先干掉库
2drop database work_oa
3
4# 恢复
5mysql --max_allowed_packet=100M -u root -p work_oa < 1.sql
6mysql --max_allowed_packet=100M -u root -p work_oa < 2.sql
7mysql --max_allowed_packet=100M -u root -p work_oa < 3.sql
8mysql --max_allowed_packet=100M -u root -p work_oa < 4.sql
9mysql --max_allowed_packet=100M -u root -p work_oa < 5.sql
10mysql --max_allowed_packet=100M -u root -p work_oa < 6.sql
11mysql --max_allowed_packet=100M -u root -p work_oa < 7.sql
12mysql --max_allowed_packet=100M -u root -p work_oa < 8.sql
13mysql --max_allowed_packet=100M -u root -p work_oa < 9.sql
这样就恢复完了。如果是在阿里云,那就是恢复到了一个新实例的新库里,然后在把库表导出,再导入到老库中,就是一个完美的恢复了。
善后事宜:
一定要做个full backup:
1mysqldump -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之后的:
1PURGE BINARY LOGS TO 'binlog.000031';