Sunskey

日拱一卒,不期而至

0%

误删数据,如何恢复?

误删数据,如何恢复?

误差数据的4个方法

1.使用delete语句误删数据行

2.使用drop table或者truncate table语句误删数据表

3.使用drop database 语句误删除数据库

4.使用rm 命令误删除整个MySQL实例。

误删行

利用Flashback工具通过闪回把数据恢复回来。需要确保binlog_format=row和binlog_row_image=FULL

  • 恢复数据

具体恢复数据,对单个事务做如下处理

1.对于Insert语句,对应的binlog类型是write_rows_event,把它改写成delete_rows_event即可。

2.对于delete语句,将delete_rows_event改成为write_rows_event;

3.对于update,binlog里面记录了数据行修改前和修改后的值,对调这两行的位置即可。

对于多个事务,则需要将事务顺序调过来执行。

恢复数据比较安全的做法,是恢复出一个备份,找一个从库作为临时库,在这个临时库上执行这些操作,然后在将确认过的临时库的数据,恢复回主库。

  • 如何预防

1.把sql_safe_updates参数设置为on,如果在update或者update写where条件或者没有包含索引,这条语句的执行就会报错。

2.代码上线前,必须经过SQL审计。

误删库/表

这种情况下,想要恢复数据,就需要使用全量备份,加增量日志的方式了。这个方案要求线上有定期的全量备份,并且实时备份binlog,恢复流程如下。

1.取出最近一次全量备份

2.用备份恢复出一个临时库

3.从日志备份里面,去除凌晨0点之后的日志

4.把这些日志,除了误删除数据的语句外,全部应用到临时库。

加速过程

1.可以使用mysqlbinlog命令,加上一个-database参数,用来指定误删除的库。

2.应用日志,需要跳过12点误操作的那个语句的binlog。

如果没有使用GTID模式,先用–stop-position参数执行到误操作之前的日志,然后再用-start-position从误操作之后的日志继续执行。

如果使用了GTID模式,那么只需要执行set gtid_next= gtid1;bengin;commit;先把这个GTID加到临时实例的GTID集合,之后按照顺序执行binlog的时候,就会自动跳过误操作的语句。

效率问题:1.如果是表,只需要重放这张表 2.mysqlbinlog解析过程是单线程,效率低。

一种加速的方法是,在用备份恢复出临时实例之后,将这个临时实例设置成线上备库的从库。

1.在 start slave 之前,先通过执行change replication filter replicate_do_table = (tbl_name) 命令,就可以让临时库只同步误操作的表;

2.这样做也可以用上并行复制技术,来加速整个数据恢复过程。

思路:误删库或者表后,恢复数据的思路主要就是备份,在加上应用binlog的方式。

延迟复制备库

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

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

预防误删库/表的方法

1.账号的分离。

  • 只给开DML权限,而不给truncate/drop权限。而如果业务开发人员有DDL需求的话,也可以开发管理系统。
  • 如果是DBA团队成员,日常也都规定只使用只读账号,必要的时候才使用更新账号。

2.制定操作规范。

  • 在删除表之前,必须先对表做改名的操作。确保无影响后,再删除这张表。

  • 改表名的是偶,要求表明加固定的后缀,然后删除表你的动作必须通过管理系统执行。

rm 删除数据

只要不是恶意地把整个集群删除,而是只删除其中的某一个节点数据的话,HA系统就会开始工作,选出一个新的主库,从而保证整个集群的正常工作。