Oracle—数据恢复

场景:在 Oracle数据库使用过程中,误删对象或误删记录的情况时有发生;这种情况下通过技术手段可以将对象的状态和数据恢复到删除前的某个时刻;

建议:技术手段的恢复毕竟是有限的,为了降低类似的误操作还是要通过规范的流程和定期的备份来规避,就像是车技再好的车手也不该经常在悬崖边漂移,否则可能都来不及说再见!


1、恢复原理

Oracle数据库提供了多种方式可以将数据库或对象或记录恢复到某个时间节点;
1)undo文件
说明:undo文件的数据有空间大小限制,数据库按照循环写的方式类使用,可恢复的数据也限于短时间内的操作;

2)redo日志
说明:redo日志因为有空间大小限制,和 undo文件数据类似,是循环写数据,所以可以恢复的数据时间跨度不会很大,一般只限于很短的时间内的操作;

3)archived redo(归档日志)
说明:归档日志是将online redo日志固化为文件存储下来,会占用不小的服务器空间;

4)rman备份

5)recyclebin(回收站)

1.1、recyclebin(回收站)

从ORACLE 10g开始,引入了一个叫回收站(RecycleBin)的概念,全称为Tablespace Recycle Bin。回收站实际是一个逻辑区域,它以表空间中现有已经分配的空间为基础,而不是从表空间上物理划出一个固定区域用作回收站。这意味着回收站和表空间中的对象共用存储区域、系统没有给回收站预留空间。

当表被DROP后,如果可用空间充足,并且没有对回收站进行清理,那么被DROP掉的对象会一直存在回收站中,仍然会占用空间。但是如果可用空间紧张的情况下,数据库会根据先进先出的顺序覆盖Recycle Bin中的对象。所以回收站机制也不是百分百的保险机制。另外从原理上来说它就是一个数据字典表,放置用户Drop掉的数据库对象信息。

相关操作

  • 参数状态
SQL> 
SQL> show parameter recyclebin;
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
recyclebin                           string      on

SQL> 

或者

select t.NAME, t.VALUE, t.DISPLAY_VALUE
  from v$parameter t
 where t.NAME = 'recyclebin';

---输出
   	NAME	VALUE	DISPLAY_VALUE
1	recyclebin	on	on

  • 开启关闭
    回收站的开启和关闭可以按照时效分为会话级别和系统级别;

1)会话级别

---session
alter session set recyclebin=on/off;

2)系统级别

---system
alter system set recyclebin=on/off;
  • 对象查找
    涉及的系统表或视图有
    A:RECYCLEBIN(指向 USER_RECYCLEBIN的同义词)
    B:USER_RECYCLEBIN
    C:DBA_RECYCLEBIN
---query_sql
select owner,
       object_name,
       original_name,
       operation,
       type,
       ts_name,
       createtime,
       droptime,
       dropscn,
       partition_name,
       can_undrop,
       can_purge,
       related,
       base_object,
       purge_object,
       space
  from DBA_RECYCLEBIN t
 where t.owner = '&username'
 order by t.createtime desc;

1.2、archived redo(归档日志)

  • 查询归档状态
    select name,log_mode from v$database t;

log_mode:NOARCHIVELOG 为非归档状态,current为归档状态;

或者在服务器的以sys用户登录的sqlplus 模式下执行:

SQL> 
SQL> archive log list
Database log mode              No Archive Mode
Automatic archival             Disabled
Archive destination            USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     134
Current log sequence           138
SQL> 

1.3、supplemental log(补充日志)

Oracle补充日志(附加日志)是基于常规日志的基础上,额外记录的日志信息,用于恢复数据库的逻辑状态;
补充日志(supplemental log)并非一定要再开启归档日志的情况下才可以开启;

补充日志的开启有2种粒度,一种是数据库级别,一种是表级别;补充日志可以有2种,即最小补充日志、标识关键字段补充日志两大类;

  • 状态查询
select name,
       t.SUPPLEMENTAL_LOG_DATA_MIN as log_min,
       t.SUPPLEMENTAL_LOG_DATA_PK as log_pk,
       t.SUPPLEMENTAL_LOG_DATA_UI as log_ui,
       t.SUPPLEMENTAL_LOG_DATA_FK as log_pk,
       t.SUPPLEMENTAL_LOG_DATA_ALL as log_all
  from v$database t;

开启关键字段补充日志的前提是要开启最小补充日志;如果需要开启某种标识关键字段的补充日志,会自动开启最小补充日志,无需提前开启最小补充日志;

标识关键字段的补充日志有分为基于主键、唯一索引、外键、全字段、自定义5类;

  • 开启/关闭最小附加日志
alter database add supplemental log data columns;
alter database drop supplemental log data columns;
  • 数据库级
---open key
alter database add supplemental log data(primary key) columns;
alter database add supplemental log data(primary key,unique,foreign key,all) columns;

---stop key
alter database drop supplemental log data(primary key) columns;
alter database drop supplemental log data(primary key,unique,foreign key,all) columns;

调整状态

SQL> 
SQL> select name,
  2         t.SUPPLEMENTAL_LOG_DATA_MIN as log_min,
  3         t.SUPPLEMENTAL_LOG_DATA_PK as log_pk,
  4         t.SUPPLEMENTAL_LOG_DATA_UI as log_ui,
  5         t.SUPPLEMENTAL_LOG_DATA_FK as log_pk,
  6         t.SUPPLEMENTAL_LOG_DATA_ALL as log_all
  7    from v$database t;

NAME      LOG_MIN  LOG_PK LOG_UI LOG_PK LOG_ALL
--------- -------- ------ ------ ------ -------
DEVDB     YES      YES    NO     NO     NO

SQL> 
  • 表级
---open key
alter table ${schema_name.tabel_name} add supplemental log data(primary key) columns;
alter table ${schema_name.tabel_name} add supplemental log data(primary key,unique,foreign key,all) columns;

---stop key
alter table ${schema_name.tabel_name} drop supplemental log data(primary key) columns;
alter table ${schema_name.tabel_name} drop supplemental log data(primary key,unique,foreign key,all) columns;

强调:表级关键字段补充日志在开启前,需要提前开启数据库级最小补充日志;

表级关键字段补充日志相比于数据库级,额外多一种日志粒度,为自定义关键字段日志;自定义关键字段补充日志分为有条件式和无条件式(加 always关键字);

alter table ${schema_name.tabel_name} add supplemental log group ${group_name} (keycol_1,keycol_2,keycol_3);

alter table ${schema_name.tabel_name} add supplemental log group ${group_name} (keycol_1,keycol_2,keycol_3) <always>;

---stop
alter table ${schema_name.tabel_name} drop supplemental log group ${group_name};
  • 关键查询语句
select t.owner,
       t.table_name,
       t.log_group_name,
       t.always,
       t.generated,
       cl.column_name,
       cl.position,
       cl.logging_property
  from dba_log_groups t
 inner join dba_log_group_columns cl
    on (t.owner = cl.owner and t.table_name = cl.table_name and
       t.log_group_name = cl.log_group_name)
 where 1 = 1
 and t.owner='SJZBQ_SSTB'
 and t.table_name='DJ_NSRXX'
 order by t.owner, t.table_name, t.log_group_name, cl.position;

2、恢复场景

2.1、定义删除

对于对象被误删除定义的场景,只能依靠回收站来恢复;需要确定回收站处于开启状态,且在 dba_recyclebin 里可以查到相应记录;

执行恢复操作

flashback table ${schema_name.object_name} to before drop;

对于被恢复定义的对象,索引和主键等名称处于乱码状态,需要重建;

2.2、记录删除

对象数据被误删除在没有开启归档且没有 RMAN 备份的情况下,可以依靠 Undo 数据或者 Redo 数据来恢复;

2.2.1、undo恢复

通过闪回查询确定删除前的记录:

select * from ${schema_name.object_name} as of timestamp to_timestamp('2020-07-26 17:00:50','yyyy-mm-dd hh24:mi:ss') where 1=1 and ${query_condition};

闪回操作:

flashback table ${schema_name.object_name} to timestamp to_timestamp('2020-07-26 17:00:50','yyyy-mm-dd hh24:mi:ss');

说明:这类操作需要确保 undo被删除前的数据没有被覆盖,如果执行flashback操作报错 ora-01555,则相应的回滚段数据已经被覆盖;此时这种方式已经无法恢复数据,或者只能恢复一部分;

2.2.2、redo恢复

该类恢复方式需要依赖到redo日志文件,需要确保redo文件内容没有被覆盖;

step_1:select * from v$logfile t;
在这里插入图片描述
step_2:登录数据库服务器

sqlplus '/as sysdba'
exec dbms_logmnr.add_logfile('/data/zxcp/redo05.log',options=>dbms_logmnr.new);
exec dbms_logmnr.add_logfile('/data/zxcp/redo06.log', dbms_logmnr.ADDFILE);
exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);

create table log_recover as select * from v$logmnr_contents;

select to_char(timestamp,'yyyy-mm-dd hh24:mi:ss'),sql_redo,sql_undo from log_recover  where username='xxxx' and table_name='xxxx';

---最后执行
exec dbms_logmnr.end_logmnr();

此处 sql_redo里的dml语句是当时执行的删除语句,sql_undo里的语句是对应恢复的dml语句;可以将 sql_undo 里的语句存储为动态语句循环执行;

注意:此种方式对于 lob 字段,值内容很长的,可能最终恢复的数据 lob 列的值部分记录为空;因为对于 lob 字段,数据不直接存储在表里;要想Lob 列也可以闪回,需要在数据更新前开启数据库级最小附加日志;

2.2.3、dbms_logmnr

  • dbms_logmnr.start_logmnr
begin
  -- Call the procedure
  sys.dbms_logmnr.start_logmnr(startScn => :startScn,
                               endScn => :endScn,
                               startTime => :startTime,
                               endTime => :endTime,
                               DictFileName => :DictFileName,
                               Options => :Options);
end;

说明:该方法有如上几个参数,在进行redo日志文件分析时,可以加 scn号的限制或时间戳的限制;

============================================== over ================================================

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值