误删数据的几种操作
- delete语句误删数据行
- drop table或者truncate table误删数据表
- drop database误删数据库
- rm命令误删整个MySQL实例
- 将sql_safe_updates参数设置为on,此时如果delete或者update忘记写where条件,或者where条件里面没有包含索引字段的话,这条语句执行会报错
- 代码上线前,必须经过SQL审计
误删行数据恢复可以使用Flashback工具 。
Flashback恢复数据的原理是通过修改binlog内容,拿回原库进行回放,前提是binlog_format=row和binlog_row_image=FULL 。
在使用Flashback进行恢复的时候,不建议在主库上进行操作,比较安全的做法是恢复出一个备份,或者找一个从库作为临时库,在这个临时库上执行操作,然后再将确认过的临时库的数据恢复到主库 。
误删库/表
drop table或者truncate table误删数据表无法通过Flashback工具恢复,因为binlog_format的格式即使是ROW模式,在binlog中记录的也只是一条drop table或者truncate语句,因此无法进行恢复 。
此时恢复的方式需要全量备份加增量日志的方式进行恢复,因此要求数据有定期的全量备份,并且实时备份binlog 。
假如某人在中午12点误删除了一个库里的某张表,恢复数据的流程如下:
- 取最近的一次全量备份,假设该库是一天一备,上次备份时间就是当天0点
- 用备份恢复出一个临时库
- 从日志备份里取出0点以后的日志
- 把这些日志,除了误删除数据的语句外,全部应用到临时库
- 为了加速数据恢复,如果这个临时库上有多个数据库,在使用mysqlbinlog命令时可以增加--database参数指定误删的表所在的数据库,避免在恢复数据时还要应用其他库日志的情况
- 应用日志在跳过误删语句的binlog时:如果原实例没有使用GTID模式,只能先通过--stop-position恢复到误操作之前的日志,然后再用--start-position从误删操作之后的日志继续执行;如果实例使用了GTID模式,只需要执行set gtid_nex=gtid1;begin;commit;将该GTID加到临时库的GTID集合,之后在应用binlog时会自动跳过误操作的语句
- 如果我们只是误删的表,但是mysqlbinlog工具并不能指定只解析一个表的日志
- mysqlbinlog解析出日志以后,应用日志的过程是单线程,无法使用并行复制 。
在用备份恢复出临时实例以后,将这个临时实例设置成线上备库的从库:
- 将误删表的gtid加入临时库
- 然后建临时库设置为线上备库的从库,临时库就可以并行复制备库的binlog
延迟复制备库
以上恢复都具有时间不可控性,如果采用上述步骤进行恢复,建议开发成工具(甚至可以做自己的DBA自动化平台),并大量测试后进行使用,避免手动误操作带来更大的问题 。
一般的主备复制存在的问题是,假设主库上的表被删除,这个命令很快会被发给所有从库,进而导致从库的数据表也被一起误删除 。
【MySQL误删数据后切勿跑路】延迟复制备库是可以持续保持与主库有N秒延迟的备库 。
CHANGE MASTER TO MASTER_DELAY=N;
假设这里N=3600,那么表示只要在1个小时以内发现了误删除,就可以的到备库上执行stop slave,再通过之前讲到的方法,跳过误操作的命令(比如将误删除的GTID加到实例集合中),就可以恢复出需要的数据 。rm误删
只要你的集群是高可用,如果rm删除了某个节点(只要不是恶意删除所有节点),HA系统会自动开始工作,选出一个新的主库,从而保证集群工作 。
推荐阅读
- mysql误删除恢复
- 如何判断MySQL实例出了问题
- 女性胸越大,越“败家”
- MySQL GTID主备切换协议
- 阿里大佬作出解释:MySQL真的不建议delete删除数据
- 公司用的 MySQL 团队开发规范,太详细了,建议收藏
- 详细介绍MySQL中约束的用法
- 故障分析 | 数据库故障 MHA 未切换
- Word中多行姓名对齐设置,多个数据快速对齐
- 数据库 SQL 约束之 NOT NULL