MySQL 误删数据应该怎么处理?

如此处理各种情况下的误删数据

delete 语句删除

用 delete 语句误删了数据行,可以用 Flashback 工具通过闪回把数据恢复回来。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_rows 的话,binlog 里面记录了数据行修改前和修改后的值,对调这两行的位置即可。

如果要恢复多个事务,需要顺序反过来执行。

Flashback 解析到的日志需要反过来执行,并且最好找一个临时库恢复出一个备份,确认没问题再恢复到主库。

预防误删的策略:
1、将sql_safe_updates参数设置为on, 这样delete或者update语句没有写where条件的话,就会报错。
2、代码上线前要求SQL审计

drop table 或者 truncate table

使用drop table或者truncate table删除数据,即使binlog_format=row,记录的binlog还是statement格式。

这时候只有使用全量备份 + 增量备份,这个方案要求线上有定期的全量备份,并且实时备份binlog。

方法是:

  1. 取最近一次全量备份;
  2. 用备份恢复出一个临时库;
  3. 将全量备份后产生的增量日志应用到临时库,增量日志需要剔除掉误操作的记录。

mysqlbinlog 支持 --database 同步某个数据库,但不支持指定数据表。

怎么跳过误删除的那个记录?

  1. 无gtid。--stop-position 应用误操作之前的日志,--start-position从误操作之后的日志继续执行
  2. 有gtid。假设误操作的gtid是gtid1,那么只需要执行
    set gtid_next=gtid1;begin;commit;加到临时实例的gtid集合,之后按顺序执行binlog,自动跳过误操作的语句。

延迟复制备库
如果有非常核心的业务,不允许太长的恢复时间,我们可以考虑搭建延迟复制的备库。这个功能是 MySQL 5.6 版本引入的。

延时复制的备库是一种特殊的备库,通过 CHANGE MASTER TO MASTER_DELAY = N 命令,可以指定这个备库持续保持跟主库有 N 秒的延迟。

drop database

预防为主,账号分离,日常只使用只读账号。制作规范,比如删除表前重命名表为xxx_to_deleted, 观察没问题后通过管理系统删除。

rm命令删除这个MySQL实例

对于一个有高可用机制的 MySQL 集群来说,最不怕的就是 rm 删除数据了。只要不是恶意地把整个集群删除,而只是删掉了其中某一个节点的数据的话,HA 系统就会开始工作,选出一个新的主库,从而保证整个集群的正常工作。这时,你要做的就是在这个节点上把数据恢复回来,再接入整个集群。

posted @ 2022-04-17 14:48  yihailin  阅读(688)  评论(0编辑  收藏  举报