MySQL数据库(故障排除)

公司的MySQL数据库在做日常巡检时发现丢失了一百万条数据,怎么办?

这是一起非常严重的数据丢失事件。请立即停止所有可能写入数据的操作 ,并按照以下紧急流程处理。注意:不要重启数据库,不要随意执行repaircheck命令,以免覆盖可能的恢复线索。

一、紧急止损与取证

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 条件
  • 重要操作前锁表或备份
  • 开启安全日志审计
相关推荐
2303_821287381 小时前
如何清洗SQL输入数据_使用框架内置的ORM处理数据交互
jvm·数据库·python
清风雅雨1 小时前
AI编程:OA流程明细表中多个金额字段由整数改为2位小数
数据库·ai编程
菜鸟上路_lbz1 小时前
sqlserver存储过程查询缓慢锁表分析
数据库·sqlserver
Elastic 中国社区官方博客1 小时前
在 Elasticsearch 中使用利润率与流行度加权来优化电商搜索
大数据·数据库·elasticsearch·搜索引擎·全文检索
van久2 小时前
Day32:项目性能优化(EF Core + 分页 + 全异步)
数据库·oracle·性能优化
shaoming37762 小时前
浏览器动作开发:地址栏图标点击事件、弹出页面设计
android·mysql·adb
Dxy12393102162 小时前
Python请求方式介绍:JSON、表单及其他常见数据传输格式
数据库·python·json
环流_4 小时前
Redis中string类型的应用场景
数据库·redis·缓存
倔强的石头_4 小时前
拒绝被复杂报表拖垮!HTAP场景下“标量子查询消除”硬核调优指南
数据库