公司的MySQL数据库在做日常巡检时发现丢失了一百万条数据,怎么办?
这是一起非常严重的数据丢失事件。请立即停止所有可能写入数据的操作 ,并按照以下紧急流程处理。注意:不要重启数据库,不要随意执行repair或check命令,以免覆盖可能的恢复线索。
一、紧急止损与取证
1、禁止执行任何写入 / 删除 / 更新
禁止重启 MySQL
禁止执行 OPTIMIZE / TRUNCATE / DROP 等危险命令
设置数据库只读
SET GLOBAL read_only = ON;
-- 同时需要关闭super用户的写入权限
SET GLOBAL super_read_only = ON;
通知开发 / 业务暂停对丢失数据所在表的写入操作。
2、立即备份现场关键日志
将所有binlog文件完整拷贝到备份目录:
cp /var/log/mysql/binlog.* /safe/location/
执行以下命令保存现场:
-- 查看表当前数据量 SELECT COUNT(*) FROM 丢失数据表;
-- 查看表最后写入时间 SELECT MAX(create_time),MAX(update_time) FROM 丢失数据表;
-- 查看数据库状态 SHOW MASTER STATUS; SHOW SLAVE STATUS\G;
3、确认丢失范围
确定是哪张表、哪个时间范围的数据丢失
检查是否有其他表也受到影响
通过业务方确认丢失数据的大致特征
4、确认是真丢失 还是查询条件错误
先排除低级问题:
是不是查询加了 WHERE 条件?
是不是连错库 / 连错表?
是不是被逻辑删除(is_deleted=1)?
-- 查是否被逻辑删除 SELECT COUNT(*) FROM 表 WHERE is_deleted=1;
二、排查原因
1、谁删的?
检查general_log(如果已开启);检查应用发布记录、数据库账号权限变更
2、怎么删的?
用mysqlbinlog解析binlog,过滤DELETE语句:
mysqlbinlog --base64-output=decode-rows -vv binlog.0000xx | grep -C 20 "DELETE FROM your_table"
3、什么时间删的?
通过业务日志、监控系统定位最早发现缺失的时间点,结合binlog时间戳
4、常见原因
人为误操作:DELETE忘带WHERE、脚本逻辑错误
应用bug:代码中批量删除逻辑触发
触发器/存储过程:级联删除
主从问题:从库被意外写入后同步覆盖
黑客入侵/删库跑路
三、数据恢复
1、基于binlog回滚
定位删除事件在binlog中的位置
mysqlbinlog --start-datetime="2025-01-15 10:00:00" --stop-datetime="2025-01-15 11:00:00" binlog.0000xx > event.sql
查看当前 binlog 文件
SHOW MASTER STATUS;
记录:mysql-bin.000123
解析 binlog,找到误删除语句
mysqlbinlog --base64-output=decode-rows -v mysql-bin.000123 > binlog.sql
打开 binlog.sql 搜索:
DELETE FROM DROP TABLE TRUNCATE
找到删除时间点、位置号(pos)。
使用 binlog2sql 或 my2sql 等工具可以反向生成恢复SQL
pip install binlog2sql
binlog2sql --flashback --start-file=binlog.0000xx --start-position=123 --stop-position=456
将生成的恢复SQL在测试库验证
确认无误后,恢复回生产库(注意避开新的写入)
恢复命令示例:
python binlog2sql.py \
-h 127.0.0.1 -u root -p密码 \
-d 库名 -t 表名 \
--start-file="mysql-bin.000123" \
--start-position=4321 \
--stop-position=9876 \
--flashback > rollback.sql
执行回滚 SQL
mysql -u root -p 库名 < rollback.sql
2、主从架构
如果配置了延时复制从库(例如延时1小时),且数据丢失在此窗口内:
-- 在从库停止同步,并跳过错删的GTID
STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; -- 谨慎使用
START SLAVE;
-- 然后从从库导出丢失数据
3、没有 binlog
找最近一次全量备份(xtrabackup/ mysqldump)
恢复到临时库
导出丢失表
导入生产库
四、恢复后验证与复盘
-- 1. 比对数据量
SELECT COUNT(*) FROM your_table WHERE create_time BETWEEN '时间范围';
-- 2. 抽样比对数据内容
SELECT * FROM your_table LIMIT 10 OFFSET 某个丢失段;
-- 3. 检查是否有主键冲突或数据乱序
加强规范:
- 限制 delete 权限
- 必须加 where 条件
- 重要操作前锁表或备份
- 开启安全日志审计