MySQL 31 误删数据后除了跑路,还能怎么办?
传统的高可用架构不能预防误删数据的,因为主库的一个drop table命令,会通过binlog传给所有从库和级联从库,进而导致整个集群的实例都会执行这个命令。
MySQL相关误删数据主要有以下几种可能:
使用delete语句误删数据行;
使用drop table或truncate table语句误删数据表;
使用drop database误删数据库;
使用rm误删整个MySQL实例。
误删行
如果使用delete语句误删数据行,可以用Flashback工具通过闪回将数据恢复。原理是修改binlog的内容,拿回原库重放。能使用该方案的前提是需要确保binlog_format=row
和binlog_row_image=FULL
。
具体而言:
对于insert,对应的binlog event类型是Write_rows event,改成Delete_rows event即可;
对于delete,将Delete_rows event改为Write_rows event;
对于update,对调binlog里修改前后的两行位置即可。
如果误操作不止一个,比如是三个事务:
(A)delete
(B)insert
(C)update
若要恢复,用Flashback解析binlog后,写回主库的命令是:
(reverse C)update
(reverse B)delete
(reverse A)insert
即误操作涉及多事务时,需要将事务顺序反过来执行。
恢复数据比较安全的做法,是找一个从库作为临时库,在临时库上执行这些操作,然后再将确认过的临时库的数据,恢复回主库。因为一个执行线上逻辑的主库,数据状态的变更往往是有关联的,可能由于误操作导致后续逻辑修改了其他关联数据,这时如果单独恢复误操作的数据,可能会出现对数据的二次破坏。
当然,更重要的是做到事前预防,有两个建议:
设置
sql_safe_updates=on
,这样如果delete或update中没写where,或where条件里没有包含索引字段,该语句的执行就会报错;代码上线前,必须经过SQL审计。
那么当设置sql_safe_updates=on
,想要删除一个小表的全部数据,该怎么办呢?
可以在delete语句加上where id>=0。该方法很慢,性能不好;
使用truncate table/drop table,缺点是无法通过Flashback恢复,因为binlog里只有一个truncate/drop语句,恢复不出数据。
误删库/表
此时想恢复数据,需要使用全量备份+增量日志的方式,因此方案要求线上有定期的全量备份,并且实时备份binlog。
假设中午12点误删了一个库,那么恢复流程如下:
取最近一次全量备份,假设该库一天一备,上次备份为当前0点;
用备份恢复出一个临时库;
从日志备份里取出凌晨0点后的日志;
将这些日志,除了误删数据的语句,全应用到临时库。
该过程有几个需要说明的地方:
为加速数据恢复,若临时库上有多个数据库,可以在使用mysqlbinlog命令时加上-database参数指定误删表所在的库,避免在恢复数据时还要应用其他库日志的情况;
应用日志需要跳过误操作语句的binlog:
如果原实例没有使用GTID模式,只能在应用到包含12点的binlog文件时,先用-stop-position参数执行到误操作前的日志,再用-start-position从误操作后的日志继续执行;
如果实例使用GTID模式,假设误操作命令的GTID是gtid1,只需执行
set gtid_next=gtid1;begin;commit;
,先将这个GTID加到临时实例的GTID集合,之后按顺序执行binlog时就会自动跳过误操作的语句。
但该方法恢复数据还是不够快,主要两个原因:
如果是误删表,最好是只恢复这张表,但mysqlbinlog并不能指定只解析一个表的日志;
应用日志的过程只能是单线程。
一种加速的方法是,在用备份恢复出临时实例后,将这个临时实例设置成线上备库的从库,这样:
在start slave之前,先通过执行
change replication filter replicate_do_table=(tbl_name)
,可以让临时库只同步误操作的表;这样做可以用上并行复制。
不论是把mysqlbinlog工具解析出的binlog文件应用到临时库还是把临时库接到备库,两个方案的共同点是:误删表/库后,恢复的思路主要是通过备份,再加上应用binlog的方式。即都要求备份系统定期备份全量日志,且需确保binlog在从本地删除前已经做了备份。
但一个系统不可能备份无限的日志,还需要根据成本和磁盘空间资源设定一个日志保留的天数。
延迟复制备库
虽然可以利用并行复制来加速恢复数据的过程,但该方案仍存在恢复时间不可控的问题。如果一个库的备份特别大,或误操作时间距离上一个全量备份的时间较长,比如一周一备的实例,在备份后的第6天发生误操作,那就需要恢复6天的日志,该恢复时间可能会按天计算。
如果有非常核心的业务,不允许太长的恢复时间,可以考虑搭建延迟复制的备库。
一般的主备复制结构存在的问题是,如果主库上有个表被误删,该命令很快会被发给所有从库,进而导致所有从库的数据表一起被误删。
延迟复制的备库是一种特殊备库,通过CHANGE MASTER TO MASTER_DELAY=N
,可以指定这个备库持续保持跟主库有N秒延迟。比如设置N=3600
,表示如果主库上有数据被误删,且在1小时内发现了该误操作命令,这个命令就还没在延迟复制的备库执行,此时到备库上执行stop slave,再通过之前介绍的方法,跳过误操作命令,就可以恢复出需要的数据。
这样就得到了一个只需要最多再追一小时,就能恢复出数据的临时实例,也就缩短了整个数据恢复需要的时间。
预防误删库/表的方法
这里给出两条建议:
账号分离,目的是避免写错命令,如:
只给业务开发DML权限而不给truncate/drop权限,如果业务开发有DDL需求,也可以通过开发管理系统得到 支持;
即使是DBA团队成员,日常也只使用只读账户,必要时才使用有更新权限的账户。
制定操作规范,目的是避免写错要删除的表名,如:
删除数据表前,必须先对表做改名,然后观察一段时间,确保对业务无影响后再进行删除;
改表名时,要求给表名加固定后缀如_to_be_deleted,然后删除表的动作必须通过管理系统执行,且删除表只能删除固定后缀的表。
rm删除数据
只要不是恶意删除整个集群,只是删除其中某一个节点的数据的话,HA系统会选出一个新主库,从而保证整个集群的正常工作。
此时要做的就是在这个节点上把数据恢复回来,再接入整个集群。
如果出现批量下线机器的操作,导致整个MySQL集群的所有节点都全军覆没。这种情况,建议只能说尽量将备份跨机房,或最好是跨城市保存。
MySQL 31 误删数据后除了跑路,还能怎么办?的更多相关文章
- mysql优化, 删除数据后物理空间未释放(转载)
mysql优化, 删除数据后物理空间未释放(转载) OPTIMIZE TABLE 当您的库中删除了大量的数据后,您可能会发现数据文件尺寸并没有减小.这是因为删除操作后在数据文件中留下碎片所致.OPTI ...
- MySQL数据库无完整备份删库,除了跑路还能怎么办?
1.背景 前段时间,由于运维同事的一次误操作,清空了内网核心数据库,导致了公司内部管理系统长时间不可用,大量知识库内容由于没有备份险些丢失. 结合这两天微盟的删库跑路事件,我们可以看到,数据库的备份与 ...
- mysql数据库从删库到跑路之select单表查询
一 介绍 本节内容: 查询语法 关键字的执行优先级 简单查询 单条件查询:WHERE 分组查询:GROUP BY HAVING 查询排序:ORDER BY 限制查询的记录数:LIMIT 使用聚合函数查 ...
- nodejs操作 mongoose(mongodb)和Sequelize(mysql)查询数据后添加新属性未生效
最近在着手koa时候,发现mongoose(mongodb)查询数据库后添加新属性,前端拿不到新属性问题, 然后测试了一下Sequelize(mysql),发现也有同样的问题存在.此时着手干! 1.1 ...
- mysql数据库从删库到跑路之mysql存储引擎
一 什么是存储引擎 mysql中建立的库===>文件夹 库中建立的表===>文件 现实生活中我们用来存储数据的文件应该有不同的类型:比如存文本用txt类型,存表格用excel,存图片用pn ...
- mysql数据库从删库到跑路之mysql数据类型
一 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 详细参考: http://www.runoob.com/mysql/mysql-data ...
- 【MYSQL】删除数据后自动增长列归0的问题
在清空数据表后发现自动增长id列在新增数据后仍然会按照之前的顺序生成 强迫症,就是想清空数据后让id从0开始,于是百度 执行以下sql语句可以让自动增长列归0 truncate table 表名 这是 ...
- 删库到跑路?还得看这篇Redis数据库持久化与企业容灾备份恢复实战指南
本章目录 0x00 数据持久化 1.RDB 方式 2.AOF 方式 如何抉择 RDB OR AOF? 0x01 备份容灾 一.备份 1.手动备份redis数据库 2.迁移Redis指定db-数据库 3 ...
- mysql数据库从删库到跑路之mysql基础
一 数据库是什么 之前所学,数据要永久保存,比如用户注册的用户信息,都是保存于文件中,而文件只能存在于某一台机器上. 如果我们不考虑从文件中读取数据的效率问题,并且假设我们的程序所有的组件都运行在一台 ...
- mysql数据库从删库到跑路之mysql:视图、触发器、事务、存储过程、函数
mysql:视图.触发器.事务.存储过程.函数 一.视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,可以将该结果 ...
随机推荐
- 另辟蹊径:利用代理驱动绕过JDBC Attack检测
0x01起因 以前徐师傅刚公开H2 JDBC RCE的时候我就用来打致远,打了大概两年然后修了最开始是直接用反斜线就可以绕过,后面添加了下面的判断. 新增了一个com.seeyon.ctp.giant ...
- H20 大模型推理系统环境配置踩坑
基础环境 CPU:INTEL(R) XEON(R) PLATINUM 8558P 48 Cores 96 Threads × 2 GPU:NVIDIA H20-3e NVL 141G × 8,NVLI ...
- PLC通过lora网关采集温室大棚温湿度数据
概述: 运用lora网关远程控制大棚内风机,日光灯,温湿度传感器等设备.可以实现远程获取现场环境的空气温湿度.土壤水分温度.二氧化碳浓度.光照强度可以自动控制温室湿帘风机.喷淋滴灌.加温补光等设备,并 ...
- 串口wifi模块、串口无线模块
串口无线模块ZLSN7046T是上海卓岚推出的wifi转串口模块.它能够将wifi信号转化为串口信号,且支持多种功能,邮票孔封装,体积小巧可以外置天线或者内置天线.7046T支持一个UART TTL电 ...
- java基础--自定义异常类、包、模板模式
自定义异常类 需求: 模拟feiQ上线的时候,如果没有插上网线,那么就抛出一个没有插上网线的异常, 如果已经插上了网上,那么就正常显示好友列表. 自定义异常类的步骤: 自定义一个类继承Exceptio ...
- java基础---构造函数
封装 封装的步骤: 1. 使用private修饰需要被封装的属性. 2. 根据需要提供get或者set方法设置以及获取属性. 封装的好处: 1. 提高了数据的安全性. 2. 操作简单. 3. 隐藏了实 ...
- 样本量的确定与OC函数
在之前的假设检验文章中我们说过,在样本量固定的情况下,第一类错误的减少必然会导致第二类错误的增加.按照之前的例子,原假设依旧是一家馒头店每天卖出100个馒头,现在如果减少第一类错误(也就是减少显著性水 ...
- batocera添加游戏
进入batocera系统之后,会发现就只有几个不懂什么东西的模拟器,或者FC和其它,好象没有发现可以用NS或者其它的模拟器,在此说明 一下: 整个系统至少支持73个以上模拟器,主界面没有仅因为你没有放 ...
- vite+vue3/react使用tailwindcss
vite+vue3/react使用 1.通过 npm 安装 Tailwind npm install -D tailwindcss postcss autoprefixer 2.创建您的配置文件 np ...
- SciTech-Mathmatics-Probability+Statistics-Population Vs. Sampling: Representative Samples + How to obtain Samples
Difference: Population vs. Sample BY ZACH BOBBITTPOSTED ON NOVEMBER 27, 2020 Often in statistics we' ...