资讯专栏INFORMATION COLUMN

【Oracle数据库】手滑删错数据,一步步教你如何挽救?

马龙驹 / 1559人阅读

摘要:前言常在河边走,哪能不湿鞋今天有客户联系说误更新数据表,导致数据错乱了,希望将这张表恢复到一周前的指定时间点。

前言

常在河边走,哪能不湿鞋?

今天有客户联系说误更新数据表,导致数据错乱了,希望将这张表恢复到 一周前 的指定时间点。

  • 数据库版本为 11.2.0.1
  • 操作系统是 Windows64
  • 数据已经被更改超过1周时间
  • 数据库已开启归档模式
  • 没有DG容灾
  • 有RMAN备份

下面模拟一下问题的详细解决过程!

一、分析

以下只列出常规恢复手段:

  • 数据已经误操作超过一周,所以排除使用UNDO快照来找回;
  • 没有DG容灾环境,排除使用DG闪回;
  • 主库已开启归档模式,并且存在RMAN备份,可使用RMAN异机恢复表对应表空间,使用DBLINK捞回数据表;
  • Oracle 12C后支持单张表恢复;

结论:安全起见,使用RMAN异机恢复表空间来捞回数据表。

二、思路

客户希望将表数据恢复到 <2021/06/08 17:00:00> 之前某个时间点。

大致操作步骤如下:

  • 主库查询误更新数据表对应的表空间和无需恢复的表空间。
  • 新主机安装Oracle 11.2.0.1数据库软件,无需建库,目录结构最好保持一致。
  • 主库拷贝参数文件,密码文件至新主机,根据新主机修改参数文件和创建新实例所需目录。
  • 新主机使用修改后的参数文件打开数据库实例到nomount状态。
  • 主库拷贝备份的控制文件至新主机,新主机使用RMAN恢复控制文件,并且MOUNT新实例。
  • 新主机RESTORE TABLESPACE恢复至时间点 <2021/06/08 16:00:00>
  • 新主机RECOVER DATABASE SKIP TABLESPACE恢复至时间点 <2021/06/08 16:00:00>
  • 新主机实例开启到只读模式。
  • 确认新主机实例的表数据是否正确,若不正确则重复 第7步 调整时间点慢慢往 <2021/06/08 17:00:00> 推进恢复。
  • 主库创建连通新主机实例的DBLINK,通过DBLINK从新主机实例捞取表数据。

? 注意: 选择表空间恢复是因为主库数据量比较大,如果全库恢复需要大量时间。

三、测试环境模拟

为了数据脱敏,因此以测试环境模拟场景进行演示!

⭐️ 测试环境可以使用脚本安装,可以使用博主编写的 Oracle 一键安装脚本,同时支持单机和 RAC 集群模式!

开源项目:Install Oracle Database By Scripts!

更多更详细的脚本使用方式可以订阅专栏:Oracle一键安装脚本

1、环境准备

测试环境信息如下:

节点主机版本主机名实例名Oracle版本IP地址
主库rhel6.9orclorcl11.2.0.110.211.55.111
新主机rhel6.9orcl不创建实例11.2.0.110.211.55.112

2、模拟测试场景

主库开启归档模式:

sqlplus / as sysdba## 设置归档路径alter system set log_archive_dest_1="LOCATION=/archivelog";## 重启开启归档模式shutdown immediatestartup mountalter database archivelog;## 打开数据库alter database open;

创建测试数据:

sqlplus / as sysdba## 创建表空间create tablespace lucifer datafile "/oradata/orcl/lucifer01.dbf" size 10M autoextend off;create tablespace ltest datafile "/oradata/orcl/ltest01.dbf" size 10M autoextend off;## 创建用户create user lucifer identified by lucifer;grant dba to lucifer;## 创建表conn lucifer/lucifercreate table lucifer(id number not null,name varchar2(20)) tablespace lucifer;## 插入数据insert into lucifer values(1,"lucifer");insert into lucifer values(2,"test1");insert into lucifer values(3,"test2");commit;

进行数据库全备:

rman target /## 进入 rman 后执行以下命令run {allocate channel c1 device type disk;allocate channel c2 device type disk;crosscheck backup;crosscheck archivelog all; sql"alter system switch logfile";delete noprompt expired backup;delete noprompt obsolete device type disk;backup database include current controlfile format "/backup/backlv0_%d_%T_%t_%s_%p";backup archivelog all DELETE INPUT;release channel c1;release channel c2;}

模拟数据修改:

sqlplus / as sysdbaconn lucifer/luciferdelete from lucifer where id=1;update lucifer set name="lucifer" where id=2;commit;

? 注意: 为了模拟客户环境,假设无法通过UNDO快照找回,当前删除时间点为:<2021/06/17 18:10:00>

如果使用UNDO快照,比较方便:

sqlplus / as sysdba## 查找UNDO快照数据是否正确select * from lucifer.lucifer as of timestamp to_timestamp("2021-06-17 18:05:00","YYYY-MM-DD HH24:MI:SS");## 将UNDO快照数据捞至新建表中create table lucifer.lucifer_0617 as select * from lucifer.lucifer as of timestamp to_timestamp("2021-06-17 18:05:00","YYYY-MM-DD HH24:MI:SS");

四、RMAN完整恢复过程

主库查询误更新数据表对应的表空间和无需恢复的表空间:

sqlplus / as sysdba## 查询误更新数据表对应表空间select owner,tablespace_name from dba_segments where segment_name="LUCIFER";## 查询所有表空间select tablespace_name from dba_tablespaces;

主库拷贝参数文件,密码文件至新主机,根据新主机修改参数文件和创建新实例所需目录:

## 生成pfile参数文件sqlplus / as sysdbacreate pfile="/home/oracle/pfile.ora" from spfile;exit;## 拷贝至新主机su - oraclescp /home/oracle/pfile.ora 10.211.55.112:/tmpscp $ORACLE_HOME/dbs/orapworcl 10.211.55.112:$ORACLE_HOME/dbs## 新主机根据实际情况修改参数文件并且创建目录mkdir -p /u01/app/oracle/admin/orcl/adumpmkdir -p /oradata/orcl/mkdir -p /archivelogchown -R oracle:oinstall /archivelogchown -R oracle:oinstall /oradata

新主机使用修改后的参数文件打开数据库实例到nomount状态:

sqlplus / as sysdbastartup nomount pfile="/tmp/pfile.ora";

主库拷贝备份的控制文件至新主机,新主机使用RMAN恢复控制文件,并且MOUNT新实例:

rman target /list backup of controlfile;exit;## 拷贝备份文件至新主机scp /backup/backlv0_ORCL_20210617_107548592* 10.211.55.112:/tmpscp /u01/app/oracle/product/11.2.0/db/dbs/0c01l775_1_1 10.211.55.112:/tmp## 新主机恢复控制文件并开启到mount状态rman target /restore controlfile from "/tmp/backlv0_ORCL_20210617_1075485924_9_1";alter database mount;

通过 list backup of controlfile; 可以看到控制文件位置:

新主机RESTORE TABLESPACE恢复至时间点 <2021/06/17 18:06:00>

## 新主机注册备份集rman target /catalog start with "/tmp/backlv0_ORCL_20210617_107548592";crosscheck backup;delete noprompt expired backup;delete noprompt obsolete device type disk;## 恢复表空间LUCIFER和系统表空间,指定时间点 `2021/06/17 18:06:00`run {sql "alter session set nls_date_format="yyyy-mm-dd hh24:mi:ss"";set until time "2021-06-17 18:06:00";allocate channel ch01 device type disk;allocate channel ch02 device type disk;restore tablespace SYSTEM,SYSAUX,UNDOTBS1,USERS,LUCIFER;release channel ch01;release channel ch02;}

新主机RECOVER DATABASE SKIP TABLESPACE恢复至时间点 <2021/06/17 18:06:00>

rman target /run {sql "alter session set nls_date_format="yyyy-mm-dd hh24:mi:ss"";set until time "2021-06-17 18:06:00";allocate channel ch01 device type disk;recover database skip tablespace LTEST,EXAMPLE;release channel ch01;}

这里有一个小BUG: 客户环境是Windows,执行这一步最后报错,手动offline数据文件依然无法开启数据库。

解决方案:

sqlplus / as sysdba## 将恢复跳过的表空间都offline drop掉,执行以下查询结果select "alter database datafile "|| file_id ||" offline drop;" from dba_data_files where tablespace_name in ("LTEST","EXAMPLE");## 再次开启数据库alter database open read only;

? 注意: 如果显示缺归档日志,可以参考如下步骤:

sqlplus / as sysdba## 查询恢复需要的归档日志号时间 alter session set nls_date_format="yyyy-mm-dd hh24:mi:ss"; select first_time,sequence# from v$archived_log where sequence#="7";exit;## 通过备份RESTORE吐出所需的归档日志 rman target / catalog start with "/tmp/0c01l775_1_1"; crosscheck archivelog all; run { allocate channel ch01 device type disk; SET ARCHIVELOG DESTINATION TO "/archivelog";restore ARCHIVELOG SEQUENCE 7; release channel ch01; }## 再次recover进行恢复至指定时间点 2021-06-17 18:06:00 run { sql "alter session set nls_date_format="yyyy-mm-dd hh24:mi:ss""; set until time "2021-06-17 18:06:00"; allocate channel ch01 device type disk; recover database skip tablespace LTEST,EXAMPLE; release channel ch01; } 

新主机实例开启到只读模式:

sqlplus / as sysdbaalter database open read only;


确认新主机实例的表数据是否正确:

sqlplus / as sysdbaselect * from lucifer.lucifer;

? 注意: 若不正确则重复 第7步 调整时间点慢慢往 2021/06/17 18:10:00 推进恢复:

## 关闭数据库sqlplus / as sysdbashutdown immediate; ## 开启数据库到mount状态startup mount pfile="/tmp/pfile.ora";## 重复 第7步,往前推进1分钟,调整时间点为 `2021/06/08 18:07:00`rman target /run {sql "alter session set nls_date_format="yyyy-mm-dd hh24:mi:ss"";set until time "2021-06-17 18:07:00";allocate channel ch01 device type disk;recover database skip tablespace LTEST,EXAMPLE;release channel ch01;}

主库创建连通新主机实例的DBLINK,通过DBLINK从新主机实例捞取表数据:

sqlplus / as sysdba## 创建dblinnkCREATE PUBLIC DATABASE LINK ORCL112CONNECT TO luciferIDENTIFIED BY luciferUSING "(DESCRIPTION_LIST=(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.211.55.112)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl))))";## 通过dblink捞取数据create table lucifer.lucifer_0618 as select /*+full(lucifer)*/ * from lucifer.lucifer@ORCL112;select * from lucifer.lucifer_0618;


至此,整个RMAN恢复过程就结束了!

写在最后

备份永远是最后一道防线,所以备份一定要做好!!!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/123152.html

相关文章

  • 步步教你用HTML5 SVG实现动画效果

    摘要:翻译疯狂的技术宅原文本文首发微信公众号欢迎关注,每天都给你推送新鲜的前端技术文章摘要在这篇文章中你将了解网是怎样实现动画的。是一种基于的,用于定义缩放矢量图形的标记语言。 翻译:疯狂的技术宅原文:https://www.smashingmagazine.... 本文首发微信公众号:jingchengyideng欢迎关注,每天都给你推送新鲜的前端技术文章 摘要在这篇文章中你将了解A...

    Ali_ 评论0 收藏0
  • Android Studio步步教你集成发布适配

    开门见山,本章教你如何配置多渠道一键打包,本教程只符合使用Android Studio的童鞋1.首先检查本地gradle版本是否是最新的,我建议换成最新的编译版本gradle版本查看 我用的是gradle-2.10-all 用迅雷下载更快https://downloads.gradle.org/distributions/gradle-2.10-all.zip 下载其它版本把2.10替换成你所需...

    CompileYouth 评论0 收藏0
  • 步步教你创建自己的数字货币(代币)进行ICO

    摘要:利用以太坊的智能合约可以轻松编写出属于自己的代币,代币可以代表任何可以交易的东西,如积分财产证书等等。要求我们在实现代币的时候必须要遵守的协议,如指定代币名称总量实现代币交易函数等,只有支持了协议才能被以太坊钱包支持。 本文首发于深入浅出区块链社区原文链接:创建自己的数字货币(ERC20 代币)进行 ICO原文已更新,请读者前往原文阅读 本文从技术角度详细介绍如何基于以太坊ERC20创...

    EddieChan 评论0 收藏0
  • Yii2:教你步步个微信商城(

    摘要:本教程主要基于大神的开源商城,为大家解读的源码,由于原版商城更多是针对国际业务,因此本教程会适当修改,使其更适合于微信环境。 本教程主要基于 terry 大神的开源商城 Fecshop,为大家解读 Fecshop 的源码,由于原版商城更多是针对国际业务,因此本教程会适当修改,使其更适合于微信环境。由于商城源码复杂,本教程将长期更新。本人也是边学习边写这份教程,过程中难免会出现错误,还请...

    Invoker 评论0 收藏0
  • 教你步步扣代码解出你需要找到的加密参数

    摘要:点击下一步,进入了这个函数内如果你调试过多次之后,发现这个是将一些加密后的字符串解密为正常的函数名字。你细心的话会发现,下面还有个打乱这个数组的函数,正确来说应该是还原数组,需要两个一起扣下来。 只收藏不点赞的都是耍流氓 注意:目前pdd已经需要登陆,这篇文章是在未更改之前写的,如果需要实践需要先登陆pdd再进行操作即可 上周的pdd很多人说看了还不会找,都找我要写一篇来教教如何扣代码...

    MRZYD 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<