MySQL 误删补救

本文将介绍 MySQL 中误删数据的补救方法。

一、注意事项

  • 代码上线前需要经过 SQL 审计

  • 误删后的补救应该在从库上执行,待确认后再恢复回主库

  • 为了避免误删行,应该将 sql_safe_updates 参数设为 on,强制要求 delete 或 update 语句加上 where 条件

  • 为了避免误删库 / 表,可以

    • 对于开发人员,只给 DML 权限

    • 对于 DBA 人员,规定日常只使用只读账号

    • 删除表之前,先做表改名操作,待观察一段时间发现没有问题后再进行删除

      可以加上固定的 deleted 后缀

    • 删除表时,只允许管理系统执行

      并且只允许删除固定后缀的表

二、误删行

如果使用 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 语句,binlog 里面记录了数据行修改前和修改后的值,对调这两行的位置
  • 如果涉及到多条语句,应该倒序执行

三、误删库 / 表

此时,需要采用全量备份 + 增量日志,要求线上有定期的全量备份,并且实时备份 binlog。

具体恢复流程为:

  • 取最近的一次全量备份
  • 用全量备份恢复出一个临时库
  • 从 binlog 备份中,取出最近一次全量备份至今的 binlog 日志
  • 将这些 binlog 日志(除了误删库 / 表的语句)应用到临时库中

四、rm 删除

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

五、延迟复制从库

从 MySQL 5.6 开始,允许配置延迟复制从库,它是一种特殊的备库,能够和主库保持 “延迟同步”。

假如把延迟设为 1 个小时,当主库上有数据被误删时,只需要在 1 个小时内发现并停止主从复制,便可以获得一个没有被误删的备用数据库。

参考

  • MySQL 技术内幕
  • MySQL 实战 45 讲
  • MySQL 是怎样运行的:从根儿上理解 MySQL