首页 > 数据库 >一条SQL更新了整个表,如何回退

一条SQL更新了整个表,如何回退

时间:2024-02-19 11:14:36浏览次数:26  
标签:恢复 数据库 更新 tab SQL 回退 RMAN order

背景:

我们的一些业务测试系统,数据库一般也是由开发同事自行维护,所以不可避免会有一些问题,经常会有开发同事火急火燎的打电话给我们,如果语气急切,态度恭谨,一般就是误操作数据了(八九不离十)。

最近我们就遇到了一起误更新数据的事件。

由于update SQL编写问题,开发同事将整个表的一个字段进行了更新。

SQL:

UPDATE tab_order a set a.status = '01'
WHERE
EXISTS (
SELECT
order_id
FROM
tab_tmp b,
tab_order c
WHERE
b.cust_no = c.cust_no
AND b.state = 3):

 

开发同事本意是希望根据tab_tmp b表的字段更新tab_order a 表的字段status值为’01’,但是由于exists里面不应该再次出现tab_order c导致子查询恒为真,全表的字段被更新。

处理方案

不同的数据库处理方式不同,但整体思路大同小异,本次事件发生在Oracle数据库上,以Oracle为例,处理误更新数据我们有几种方式:

1.事务未结束,直接rollback

Oracle数据库事务是手动提交的,如果还没有提交可能有挽回余地,但数据量比较大的话回滚时间会比较长。其它类型数据库大部分是自动提交的,因此更新数据前稳妥起见,我们可以通过显示打开事务的方式进行操作。 以Mysql为例,在自动提交模式下可以使用begin的方式打开事务: SQL> begin;
SQL> UPDATE tab_order a set a.status = '01';
SQL> rollback;

2.使用闪回查询

如果事务已经提交了,当数据库undo表空间足够,undo_retention保留时间足够长,是可能会查到修改前的原数据的。那么可以优先考虑闪回查询恢复。 SQL> show parameter unodNAME            TYPE        VALUE
---------------------------------
undo_management string      AUTO
undo_retrntion  intrger     900
undo_tablespace string      UNDOTBS1
/* 默认undo_retention为900s

SQL> SELECT * FROM tab_order a

 

AS OF TIMESTAMP TO_TIMESTAMP('2023-04-20 21:10:00', 'YYYY-MM-DD HH24:MI:SS');
/* 查询的时间应该位于 update之前的最近时刻,如果undo信息被覆盖了,会报错ORA-01555,则无法使用该方法恢复*/

/*如果闪回查询可以查到数据,可以新建一个表用来存储历史数据,进行恢复*/
SQL> CREATE TABLE tab_old as SELECT * FROM tab_order a
AS OF TIMESTAMP TO_TIMESTAMP('2023-04-20 21:10:00', 'YYYY-MM-DD HH24:MI:SS'); 除了Oracle,tidb、oceanbase等数据库也提供了这个功能。

3.使用LogMinner挖掘日志,执行undo sql恢复

如果报错ORA-01555,意味着数据已经过期,闪回查询无法查询到数据。如果能准确知道修改了哪些数据的情况下,可以优先考虑LogMinner恢复原数据。LogMinner主要依托于挖掘DML SQL执行期间生成的redo log中的原值来恢复数据,在LogMinner挖掘后日志后会看到 undo sql(回滚sql),可以用来直接恢复数据。 加入日志,如果不确定时间就多家几组日志
execute dbms_logmnr.add_logfile('/opt/oracle/archive/1_85_782895629.dbf',dbms_logmnr.new);
分析日志
execute dbms_logmnr.START_LOGMNR(options => dbms_logmnr.dict_from_online_catalog);

查询分析结果,可以按照表明 like
select username,sql_redo,sql_undo from v$logmnr_contents where operation='UPDATE' and
sql_redo like '%tab_order a%';

Mysql 的binlog 中记录了新旧值,需要通过工具生成回滚SQL,SQLServer也有类似的工具。4.使用expdp/impdp的方式恢复如果有逻辑备份且表数据未发生变动,可以考虑使用逻辑备份恢复。逻辑备份使用起来比较灵活,不过只能恢复到备份那一刻的数据,不适用数据变动频繁的业务表。

 

4.使用备份恢复异机恢复表,导出、导入恢复


本次恢复由于几个方面因素不满足,我们使用了最终的异机备份恢复的方案。

1、恢复参数文件。
设置环境变量:export ORACLE_SID=xxx
登录RMAN:rman target /
在RMAN里把数据库起到nomount状态:RMAN>  startup nomount;
设置DBID:RMAN>  set dbid=3931082997
恢复spfile:RMAN>  restore spfile from '/backup/test/c-3931082997-20131204-02';
关闭数据库:RMAN>  shutdown immediate;
把数据库起到nomount状态:RMAN>  startup nomount;
2、恢复控制文件。RMAN>  restore controlfile from '/backup/test/ctl_HNCDFHQ_20131204_21_1';
把数据库启动到mount状态:RMAN>  alter database mount;
3、恢复数据文件:
如果备份不在备份时所在的目录,在新的目录。可以用此命令注册到控制文件。RMAN>  catalog start with '/oradata1/backup';restore数据库:RMAN>  run{allocate channel c1 type disk ;allocate channel c2 type disk ;restore database ;
release channel ch1;release channel ch2;}

recover 数据库:RMAN>  recover database;SQL>  recover database until cancel using backup controlfile ;
--选择redo的绝对路径,一个一个试,有多少组redo,就试多少次SQL>  alter database open resetlogs;
/*4.恢复完使用expdp导出*/
$ expdp "'/ as sysdba'" table=userA.tab_order dumpfilefile=tab_order.dmp directory=dumpdir/* 恢复时可以新建一个用户 */$ impdp "'/ as sysdba'" dumpfile=tab_order.dmp directory=dumpdir remap_schema=userA:userB/* 然后根据恢复的表把原来的值UPDATE回来  */SQL> UPDATE userA.tab_order a , userB.tab_order b set a.status = b.tab_order where a.id=b.id  总结上面的4种方案,由上到下依次恢复成本增加,相关经验可以参考借鉴。

标签:恢复,数据库,更新,tab,SQL,回退,RMAN,order
From: https://www.cnblogs.com/ataoxz/p/18020664

相关文章

  • centos 7安装sql server 2019
    1.下载安装包: 参考地址:https://packages.microsoft.com/rhel/7/mssql-server-2019/mssql-server-15.0.4083.2-15.x86_64.rpm 找一个自己喜欢的版本,下载下来。或者找大神们的百度网盘也行。2.将文件拷贝到虚拟机目录,运行如下命令开始安装。 3.安装的时候出现缺少依赖包,使......
  • ECMAScript 语言规范每年都会进行一次更新,而备受期待的 ECMAScript 2024 将于 2024 年
    Promise.withResolvers使用Promise.withResolvers()关键的区别在于解决和拒绝函数现在与Promise本身处于同一作用域,而不是在执行器中被创建和一次性使用。这可能使得一些更高级的用例成为可能,例如在重复事件中重用它们,特别是在处理流和队列时。这通常也意味着相比在执行器内......
  • SQLite、MySQL和PostgreSQL的区别
    SQLite、MySQL和PostgreSQL都是广泛使用的开源关系型数据库管理系统(RDBMS),但它们在设计目标、适用场景和功能特性上各有特点:SQLite:简介:SQLite是一个轻量级的嵌入式数据库引擎,它不需要独立服务器进程就可以运行。SQLite数据库文件直接存储在磁盘上,应用程序通过API直接与数据库......
  • 热更新 Creator 3.x 原生平台热更新(转载)
    使用版本:3.7.1功能介绍:基于官方demo修改步骤:1.下载官方demohttps://github.com/cocos-creator/cocos-tutorial-hot-update/tree/master 1522.搭建测试服务器https://cloud.tencent.com/developer/article/1987932 92开启默认端口是8080,启动的时候可以http-server-p端口号来修......
  • 从兼容MySql的国产数据库OceanBase导出数据到MySql5.7报错解决
    现象:用MySQL的客户端或管理工具(如DBeaver/heidisql)正常导出是没有问题的,但是导入会提示错误.原因:导出时,默认建表语句添加了一些OceanBase特有的选项,MySQL不支持.打开导出的.sql文件可以看到,建表语句最后有类似: COLLATE=utf8mb4_binROW_FORMAT=DYNAMICCOMPRESSI......
  • sql注入基础知识
    sql注入基础知识前言:之前也写过sql注入的文章,但更多的是写题的记录,对一些sql注入的基本知识点没有涉及,今天来更进一步的讲解sql注入我们检测是否可以进行注入,首先要查看网站是否存在参数传递,不一定是要在url地址中含有查询字符串,数据可能通过post方式提交,更改post数据也可进行......
  • 【持续更新中】【解题报告】你非得用贪心解深搜题吗?——搜索题迷惑解法大赏
    寒假THOI集训部分深搜题目(另类)题解今日推歌:《カブってこうぜぇfeat.可不》-タケノコ少年特别可爱的一个歌,,,Before集训时候做题做出的怪异解法和迷惑大赏,真实有用的成分低于迷惑成分除了深搜以后(可能)还会有广搜题本篇没有任何以贪心为正解的题,也(几乎)没有以正解(搜索)做出来......
  • centos7安装mysql随记
    安装途中出现RPM-GPG-KEY-mysql实现问题,通过rpm--importhttps://repo.mysql.com/RPM-GPG-KEY-mysql-2022解决,如果网络不好也可以直接复制RPM-GPG-KEY-mysql-2022的内容到RPM-GPG-KEY-mysql中虚拟机版本是centos7,安装mysql5.7,把rpm文件下载好之后直接放到虚拟机上也可以通过虚......
  • docker启动mysql失败原因分析
    dockerlogsmysql 发现问题Can'treaddirof'/etc/mysql/conf.d/修改原因:原来的命令:dockerrun-p3306:3306--namemysql-v/mydata/mysql/log:/var/log/mysql-v/mydata/mysql/data:/var/lib/mysql -v/mydata/mysql/conf:/etc/mysql-eMYSQL_ROOT_PASSWORD=roo......
  • Docker 安装 MySQL8.0
    docker安装mysqldocker仓库搜索mysqldockersearchmysqldocker仓库拉取mysql8.0dockerpullmysql:8.0//默认拉取最新版本dockerpullmysql查看本地仓库镜像是否下载成功dockerimagesmysql:8.0安装运行mysql8.0容器dockerrun-p3307:3306--namem......