《MySQL——恢复数据-误删行、表、库》

传统的架构不能预防误删数据,因为主库的一个drop table命令,会通过binlog传给所有从库和级联从库,进而导致整个集群的实例都会执行这个命令。

MySQL相关的误删除数据分类:

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

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

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

4、使用rm命令误删整个MySQL实例

误删行

若使用delete语句误删数据行,可以用Flashback工具通过闪回把数据恢复。

原理:修改binlog内容,拿回原库重放。

前提:binlog_fromat = row 和binlog_row_image = FULL

具体措施:

1、对于insert语句,对应的binlog event 类型为WrIte_rows event,将其改为Delete_rows event

2、同理,对于delete,将Delete_rows event 改为Write_rows event

3、对于Update_rows,binlog记录了数据行修改前和修改后的值,对调两行位置即可

如果误操作是多个,如:

(A)delete ...
(B)insert ...
(C)update ...

若要恢复这三个事务之前状态,用Flashback工具解析binlog后,写回主库:

(reverse C)update ...
(reverse B)delete ...
(reverse A)insert ...

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

这是由于发现数据问题时间比较晚,导致会有在误操作的基础上的逻辑,如果单独恢复这个几行数据,会对数据造成二次破坏。

事前预防误删行数据方法

1、把sql_safe_updates参数设置为on。这样如果忘记在delete或者update语句中写where条件,或者where条件里没有包含索引字段,语句执行报错

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

误删表/库

需要删除一个表时,delete全表很慢,需要生成回滚日志、写redo、写binlog,所以常常使用truncate table 或者 drop table。

直接drop表和delete每行的最大区别就是,binlog对delete有详细的删除行内容,可是drop表后binlog就只有一个drop语句,恢复不了数据。

使用truncate/drop误删除数据时的恢复方法 :使用全量备份,加增量日志。要求对线上有定期的全量备份,并且实时备份binlog。

如果中午误删了库,恢复数据流程如下:

1、取最近一次全量备份,假设这个库是一天一备,上次备份是当天0点

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

3、从日志被分离,取出0点之后的日志

4、把这些日志,除了误删除的数据的语句外,全部应用到临时库
在这里插入图片描述

加速恢复数据

1、如果临时库有多个数据库,可以指定误删表所在的库,这样就避免了恢复数据时还要应用其他库日志。

2、应用日志时,跳过误操作的语句

不过这样使用mysqlbinlog方法恢复数据不够快。

mysqlbinlog恢复数据不够快的原因:不能指定特定数据表、单线程操作

另外的加速方法

在用备份恢复出临时实例之后,将这个临时实例设置成线上备库的从库。

具体流程:

1、在start slave 之前,执行change replication filter replicate_do_table = (tbl_name),让临时库只同步误操作的表

2、可以使用并行复制技术,加速数据恢复
在这里插入图片描述

延迟复制备库

如果一个库备份很大,或者误操作的时间举例上一个全备份的时间较长,可以搭建延迟复制的备库缩短恢复数据恢复需要的时间。

一般的主备复制结构存在问题:如果主库有个表被误删了,这个命令很快也会被发给所有从库,进而导致所有从库的数据表也都一起被误删。

可以主动加大同步延迟,通过CHANGE MASTER TO MASTER_DELAY = N 命令,指定这个备库始终与主库有N秒延迟。如果把N设置为3600,代表如果主库上有数据被误删了,并且在1h之内发现了这个误操作,该命令此时没有在延迟复制的备库执行,所以可以到备库上stop slave,然后跳过误操作命令,恢复数据。

事前预防误删库/表方法

1、账号分离。

只给业务开发人员DML权限,不给truncate/drop权限。

DBA团队成员,也只使用只读账号,必要时使用有更新权限的账号

2、指定操作规范,避免写错要删除的表名。

在删除数据表之前,对表进行改名操作,并观察一段时间,若对业务无影响,则删除

改表名时要给表名加固定的后缀如_to_be_deleted,然后删除表的动作必须通过管理系统执行。并且管理系统只能删除固定后缀的表。

### 使用 Navicat Premium 15 恢复 MySQL 数据库误删除的数据 #### 停止 MySQL 服务 为了最大限度减少数据丢失的风险,在发现误删之后应当立即停止 MySQL 服务。这可以防止新的事务日志被创建并覆盖旧的日志条目。 ```bash sudo systemctl stop mysql.service ``` #### 备份现有数据文件 在尝试任何恢复操作前,建议先备份现有的数据库文件夹以防万一。如果 `innodb_file_per_table` 设置为 ON,则每个 InnoDB 都有独立的 .ibd 文件;如果是 OFF,则所有共享同一个 ibdata1 文件[^2]。 对于开启了 `innodb_file_per_table` 的情况: ```bash cp -r /var/lib/mysql/*_table.ibd ~/backup/ ``` 而对于未开启的情况则需复制整个 `/var/lib/mysql/` 目录下的内容作为备份。 #### 利用二进制日志 (Binlog) 进时间点恢复 如果启用了 Binlog 功能,并且有足够的历史记录来捕捉到删除事件之前的更改,那么可以通过解析这些日志来进精确的时间点恢复。使用 Python 工具如 binlog2sql 来生成回滚 SQL 脚本是一个不错的选择[^4]: 安装依赖项: ```bash pip install pymysql==0.7.9 git clone https://github.com/danfengcui/binlog2sql.git cd binlog2sql ``` 执命令转换 binlog 至可逆向应用的 SQL 语句: ```bash python binlog2sql/binlog2sql.py \ -h localhost \ # 主机地址 -P 3306 \ # 端口号 -u root \ # 用户名 -p'password' \ # 密码 -d database_name \ # 需要处理的目标数据库名称 -t table_deleted \ # 删除了哪张 --start-file='binlog_filename' \ # 开始读取哪个 binlog 文件 --start-position=start_position_value \ # 日志中的起始位置 --stop-position=end_position_value \ # 结束的位置 -B > rollback.sql # 输出至指定路径下的 sql 文件 ``` 上述脚本会根据给定参数构建出能够撤销特定范围内变更的操作指令集合——即所谓的 "undo log" 或者说是反向 DML(DCL/DQL),从而允许管理员通过导入此文件的方式撤消错误动作的影响。 #### 应用自动生成的回滚脚本 一旦获得了合适的回滚 SQL 文件,就可以将其应用于目标实例以完成实际的数据恢复过程。在此之前记得重启 MySQL 并设置其处于单用户模式或只读状态以免再次遭受意外修改干扰。 ```sql SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; SOURCE /path/to/generated/rollback.sql ; COMMIT; ``` 最后一步就是验证所做的一切是否成功挽回损失的信息资源了! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾牙慧者

欢迎请作者喝奶茶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值