暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle误删数据的恢复

数据库驾驶舱 2024-05-14
238

背景

在数据库管理中,误删数据是一个常见且令人头疼的问题。无论是因为操作失误还是脚本错误,误删的数据可能会导致业务中断和数据丢失。然而,Oracle数据库提供了一系列强大的恢复功能,包括Undo表空间、回收站和闪回数据库
,帮助DBA快速恢复误删的数据。

前提条件

Flashback需要打开最小补全日志.
alter database add supplemental log data;  

使用如下命令来查看补全日志是否被打开.
SQL> select supplemental_log_data_min, supplemental_log_data_pk, supplemental_log_data_ui, supplemental_log_data_fk, supplemental_log_data_all from v$database;  
  
SUPPLEME SUP SUP SUP SUP  
-------- --- --- --- ---  
YES  NO  NO  NO  NO  

使用Flashback 需要当前用户具有select any transaction 权限.

基于undo

Flashback Transaction Query

-- Flashback Transaction Query可以查出事务的操作时间, xid等关键信息.

SQL> conn scott/tiger
Connected.

SQL> delete from scott.emp1 where EMPNO<7600;

4 rows deleted.

SQL> commit;

Commit complete.


-- 通过时间
select eid,eitime,eutime,numday, versions_xid, versions_startscn, versions_endscn,  
to_char(versions_starttime,'yy/mm/dd hh24:mi:ss'as startime,   
to_char(versions_endtime,'yy/mm/dd hh24:mi:ss'as endtime,   
versions_operation  
from scott.loguser versions BETWEEN timestamp to_timestamp('2024-05-14 19:50:00','yyyy-mm-dd hh24:mi:ss'and to_timestamp('2024-05-14 20:00:00','yyyy-mm-dd hh24:mi:ss'where eid > 0 and versions_operation is not null;

-- 通过scn
select current_scn from v$database;

CURRENT_SCN
-----------
  256991992

select eid,eitime,eutime,numday, versions_xid, versions_startscn, versions_endscn,  
to_char(versions_starttime,'yy/mm/dd hh24:mi:ss'as startime,   
to_char(versions_endtime,'yy/mm/dd hh24:mi:ss'as endtime,   
versions_operation  
from scott.loguser versions between scn 256991992 and 256999992 where eid > 0 and versions_operation is not null;


-- 查看误删除语句的VERSIONS_XID
     EMPNO VERSIONS_XID     VERSIONS_STARTSCN VERSIONS_ENDSCN STARTIME          ENDTIME           V
---------- ---------------- ----------------- --------------- ----------------- ----------------- -
      7566 0700170014480200         256991454                 24/05/14 19:55:10                   D
      7521 0700170014480200         256991454                 24/05/14 19:55:10                   D
      7499 0700170014480200         256991454                 24/05/14 19:55:10                   D
      7369 0700170014480200         256991454                 24/05/14 19:55:10                   D


-- 根据VERSIONS_XID找出回滚sql,指向所有的undo sql
select operation, undo_sql from flashback_transaction_query   
where xid ='0700170014480200' ;

OPERATION
--------------------------------
UNDO_SQL
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DELETE
insert into "SCOTT"."EMP1"("EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO","SEX") values ('7566','JONES','MANAGER','7839',TO_DATE('1981-04-02 00:00:00''yyyy-mm-dd hh24:mi:ss'),'2975',NU
LL,'20','female');

DELETE
insert into "SCOTT"."EMP1"("EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO","SEX") values ('7521','WARD','SALESMAN','7698',TO_DATE('1981-02-22 00:00:00''yyyy-mm-dd hh24:mi:ss'),'1250','5
00'
,'30','female');

DELETE
insert into "SCOTT"."EMP1"("EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO","SEX") values ('7499','ALLEN','SALESMAN','7698',TO_DATE('1981-02-20 00:00:00''yyyy-mm-dd hh24:mi:ss'),'1600','
300'
,'30','female');

DELETE
insert into "SCOTT"."EMP1"("EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO","SEX") values ('7369','SMITH','CLERK','7902',TO_DATE('1980-12-17 00:00:00''yyyy-mm-dd hh24:mi:ss'),'800',NULL,
'20','male');

flahback query

-- flahback query查看60分钟前的数据(利用多版本读一致性从undo tablesapce 读取操作前的记录数据)
SQL> select * from SCOTT.EMP1 as of timestamp sysdate-20/(24*60where empno<7640;

     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO SEX
---------- ---------- --------- ---------- ------------------- ---------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800                    20 male
      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30 female
      7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30 female
      7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975                    20 female

SQL> select * from SCOTT.EMP1 as of timestamp TO_TIMESTAMP('2024-05-14 19:55:10''YYYY-MM-DD HH24:MI:SS'where empno<7640;

     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO SEX
---------- ---------- --------- ---------- ------------------- ---------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800                    20 male
      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30 female
      7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30 female
      7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975                    20 female

-- 回滚数据
insert into SCOTT.EMP1 select * from SCOTT.EMP1 as of timestamp to_timestamp('2024-05-14 19:55:10''YYYY-MM-DD HH24:MI:SS'where empno<7640;

flashback table 恢复delete


-- delete全表恢复(基于回滚数据(undo data)来实现,ddl和统计信息不能恢复)
SQL> select * from t;

         C
----------
         0
         0

SQL> delete from t;

2 rows deleted.

SQL> commit;

Commit complete.

SQL> alter table t enable row movement;

Table altered.

SQL> flashback table t to timestamp to_timestamp('2024-05-14 19:00:00','yyyy-mm-dd hh24:mi:ss');

Flashback complete.

SQL> select * from t;

         C
----------
         0
         0

基于回收站

恢复drop的表

SQL> select OBJECT_NAME,ORIGINAL_NAME,OPERATION from recyclebin where ORIGINAL_NAME='T';

OBJECT_NAME
--------------------------------------------------------------------------------
ORIGINAL_NAME
--------------------------------------------------------------------------------
OPERATION
---------------------------
BIN$7WWDt6uVTczgU3QQzQoM2Q==$0
T
DROP


SQL> select * from t;
select * from t
              *
ERROR at line 1:
ORA-00942table or view does not exist


SQL> flashback table t to before drop;

Flashback complete.

SQL> select * from t;

         C
----------
         0
         0

## 还需要单独创建索引,主键等

基于闪回恢复区

-- 配置闪回恢复区:
-- 设置闪回恢复区的路径和大小,以存储闪回日志。

ALTER SYSTEM SET db_recovery_file_dest = '/path/to/recovery/area';
ALTER SYSTEM SET db_recovery_file_dest_size = 10G;  -- 设置闪回恢复区大小

ALTER SYSTEM SET DB_FLASHBACK_RETENTION_TARGET=1440 SCOPE=BOTH-- 设置保留时间为1440分钟(1天)

-- 启用闪回数据库功能
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE FLASHBACK ON;
ALTER DATABASE OPEN;

-- 查看最久的scn和时间
SELECT OLDEST_FLASHBACK_SCN, OLDEST_FLASHBACK_TIME FROM V$FLASHBACK_DATABASE_LOG;

OLDEST_FLASHBACK_SCN OLDEST_FLASHBACK_TI
-------------------- -------------------
           256452918 2024-05-14 11:56:26

-- 启动到mount
STARTUP MOUNT;
-- 闪回到10分钟前
FLASHBACK DATABASE TO TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' MINUTE);
-- 闪回到指定scn
flashback database to scn 256452918;

总结

误删数据是数据库管理中的常见问题,但通过Oracle提供的Undo表空间、回收站和闪回数据库等恢复功能,我们可以有效地应对和恢复误删的数据。这不仅提高了数据安全性,还保障了业务的连续性和可靠性。掌握这些恢复技巧,DBA可以更加从容应对意外的发生,确保数据库系统的稳定运行。

「欢迎关注我们的公众号,获取更多技术分享与经验交流。」


文章转载自数据库驾驶舱,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论