项目上开发人员误删除了数据,需要做不完全恢复,好在数据量不大,用mysqlbinlog恢复就可以了,但实际执行中还是遇到很多细节问题,这里也记录下以便以后能更快解决问题,本文将用一个实验模拟真是处理过程且通过本文实验也能彻底了解mysql不完全恢复的方法

基本环境建立

create database test default character set utf8;

create user 'testuser'@'localhost' identified by 'password';
create user 'testuser'@'%' identified by 'password';
grant all privileges on  *.* to 'testuser'@'%';
create table test_backup(
  id INT PRIMARY KEY,
  value varchar(20)
)

模拟初始化数据

INSERT INTO test_backup(id, value) VALUES (1, 'test01'), (2, 'test02'), (3, 'test03');

备份初始化后的数据

mysqldump --databases test --single-transaction --master-data=2 > /tmp/backup_test_`date +%F-%H-%M`.sql

--master-data=2 是把change log 那行注释掉,=1 是没有注释.

确定备份时的日志文件名和日志号方法

grep "^-- CHANGE MASTER TO" /tmp/backup_test_2023-04-26-02-20.sql

模拟第一天插入的数据

INSERT INTO test_backup(id, value) VALUES (4, 'test04'), (5, 'test05');

模拟第二天执行了误删除操作

delete from test_backup where id = 4
INSERT INTO test_backup(id, value) VALUES (6, 'test06');

模拟第二天发现问题开始恢复到删除之前数据

分析binlog中有delete操作的日志
mysqlbinlog /var/lib/mysql/bin-log.000006 | grep -i "delete"
#230426 18:23:42 server id 1  end_log_pos 494   Delete_rows: table id 21 flags: STMT_END_F
#230426 18:43:23 server id 1  end_log_pos 1130  Delete_rows: table id 21 flags: STMT_END_F
截取备份到删除操作之间的日志
mysqlbinlog --start-position='1257' --stop-position='1130'  /var/lib/mysql/bin-log.000005 /var/lib/mysql/bin-log.000006 > /tmp/test-bin-logall.sql
mysqlbinlog --start-position='1257' --stop-position='1130' /var/lib/mysql/bin-log.000005 /var/lib/mysql/bin-log.000006 -d test > /tmp/test-bin-logall.sql|mysql
恢复数据
mysql -uroot -ppassword
set sql_log_bin=0;
source /tmp/backup_test_2023-04-26-02-20.sql;
source /tmp/test-bin-logall.sql;

最后两步还可以合并成如下简单方法

mysql -uroot -ppassword -e 'source /tmp/backup_test_2023-04-26-02-20.sql'
mysqlbinlog --start-position='1257' --stop-position='1130' /var/lib/mysql/bin-log.000005 /var/lib/mysql/bin-log.000006 | mysql test > /tmp/test-bin-logall.sql