记一次生产事故:一年的数据被删除了
故事开始
快要下班了,心情是这样的。
突然电话响了,一看电话号码是项目甲方负责人的号码
菊花一紧,难道出什么问题了,硬着头皮接通了电话。
@####@,你们程序怎么回事 ,某个业务的数据界面一条都查询不到了。。。。。
我们马上排查一下,看看那什么情况(心理活动:尼玛,尼玛,我怎么知道啊)???
莫慌,先搞条SQL到数据库查一把 阿弥陀佛,祈祷只是查询条件的问题。
哦豁、哦豁、数据库里也没了,用户做了一年的任务数据都没了,我尼玛!!!!
甲方要求今天必须恢复数据,什么问题导致的你们后面自己排查去。
好好好,是是是
(恢复数据不都是小菜一碟的事毕竟我们数据库每天凌晨有定时全量备份,也开了binlog日志的,哈哈,这难不倒我)
恢复数据没问题啊
binlog里面把删除语句找出来,逆向改成插入语句不就恢复了,这事不就欧了。
说干就干,先让公司现场运维同事帮忙把binlog拷贝出来
开始搞binlog,通过命令: mysqlbinlog --no-defaults -vv --base64-output=decode-rows --start-datetime='2024-12-30 16:49:35' --stop-datetime='2024-12-30 17:00:00' mysql-bin.000103 >outsql1.sql;找出对应时间点的语句删除。
找到删除语句还是很顺利,但是
binlog 中的删除语句只有被删除数据的ID,没有删除数据的详细数据,tmd 这怎么搞(后面再说原因,先恢复数据要紧)
没办法只能拷贝全量备份文件了
问题又来了,公司运维说科技运维说拷贝不出来,文件太大了要拷贝1个小时(备份源文件 7G)


说明:
数据丢失的原因:程序缺陷导致,一个平常不用的功能,刚好年底了用到了
binlog里面为啥只有删除数据的ID没有详情:因为Binlog 格式设置的是“Mixed”
总结:
1、设Binlog模式要慎重,还得的按照自己项目实际情况去设置 binlog 类型,不然可能会对恢复数据造成麻烦。
binlog 有三种格式:
-
- Statement(Statement-Based Replication,SBR):每一条会修改数据的 SQL 都会记录在 binlog 中。
- Row(Row-Based Replication,RBR):不记录 SQL 语句上下文信息,仅保存哪条记录被修改。
- Mixed(Mixed-Based Replication,MBR):Statement 和 Row 的混合体。
Statement
Statement 模式只记录执行的 SQL,不需要记录每一行数据的变化,因此极大的减少了 binlog 的日志量,避免了大量的 IO 操作,提升了系统的性能。(比如update user set name="张三" where id >1 and id <10000,假设被修改的数据有2000条,那么Row的日志量就是2000条,而Statement只是这条sql语句一条日志而已,所以Statement的日志量相对Row会少很多)
但是,正是由于 Statement 模式只记录 SQL,而如果一些 SQL 中 包含了函数,那么可能会出现执行结果不一致的情况。比如说 uuid() 函数,每次执行的时候都会生成一个随机字符串,在 master 中记录了 uuid,当同步到 slave 之后,再次执行,就得到另外一个结果了。
所以使用 Statement 格式会出现一些数据一致性问题。
Row
从 MySQL5.1.5 版本开始,binlog 引入了 Row 格式,Row 格式不记录 SQL 语句上下文相关信息,仅仅只需要记录某一条记录被修改成什么样子了。
Row 格式的日志内容会非常清楚地记录下每一行数据修改的细节,这样就不会出现 Statement 中存在的那种数据无法被正常复制的情况。
不过 Row 格式也有一个很大的问题,那就是日志量太大了,特别是批量 update、整表 delete、alter 表等操作,由于要记录每一行数据的变化,此时会产生大量的日志,大量的日志也会带来 IO 性能问题。
此外,新版的MySQL中对row级别也做了一些优化,当表结构发生变化的时候,会记录语句而不是逐行记录。Mixed
从 MySQL5.1.8 版开始,MySQL 又推出了 Mixed 格式,这种格式实际上就是 Statement 与 Row 的结合。
在 Mixed 模式下,系统会自动判断 该 用 Statement 还是 Row:一般的语句修改使用 Statement 格式保存 binlog;对于一些 Statement 无法准确完成主从复制的操作,则采用 Row 格式保存 binlog。
Mixed 模式中,MySQL 会根据执行的每一条具体的 SQL 语句来区别对待记录的日志格式,也就是在 Statement 和 Row 之间选择一种。
根据这次经历发现 Mixed 某些语句下是不会记录数据详情的,我们这次的删除语句就是Delete FROM Table where ID IN (ID1,ID2),IN里面有很多ID,大量ID时 Mixed 模式下binlog是不会记录每行数据的详情地,真是血的教训换来的经验 。
2、全量备份是必要的,这次就靠全量备份活过来了,binlog的增量备份也是很必要的可以尽量减少数据丢失,但是要注意binlog的模式设置。
3、cat testdb_all.sql |grep -E ‘INSERT INTO `personchangeinfo`’ > personchangeinfo1.sql ; 这个命令很实用,可以从大文件里面查找匹配内容并输出到新文件
4、用mysqldump 备份的文件,压缩比很可观的,别忘了压缩。
相关文章
- 优化GreatSQL日志文件空间占用 GreatSQL对于日志文件磁盘空间占用,做了一些优化,对于binlog、...03-18
- "数据约束条件" date: 2022-11-24T21:24:31 08:00 draft: false MySQL字段约束条件 无符号, 零填充...03-18
【GreatSQL优化器-16】INDEX_SKIP_SCAN
【GreatSQL优化器-16】INDEX_SKIP_SCAN 一、INDEX_SKIP_SCAN介绍 GreatSQL 优化器的索引跳跃扫描(Index Ski...03-18- MySQL 是一个非常流行的开源关系数据库管理系统,在各种应用场景中都得到了广泛的应用。随...03-18
- 🤖 DB-GPT 是一个开源的 AI 原生数据应用程序开发框架,具有 AWEL(代理工作流表达式语...03-18
GreatSQL 8.0.32-27 GA (2025-3-10)
GreatSQL 8.0.32-27 GA (2025-3-10) 版本信息 发布时间:2025年3月10日 版本号:8.0.32-27, Revision aa66a38591...03-18- 6. MySQL 索引的数据结构(详细说明) @目录6. MySQL 索引的数据结构(详细说明)1. 为什么使用索引2...03-18
- @Override @Transactional(rollbackFor = Exception.class) public void batchInsertDeviceData(IotMsgNotifyData iotMsgNotifyDa...03-18
- 个人Qt项目总结——数据库查询断言问题 问题: 当我使用MySQL数据库的查询操作时, 如果查询...03-18
- MySQL 是一种广泛使用的关系数据库管理系统,MySQL 8 是其最新的主要版本,结合了出色的性能和...03-18
最新评论