在工作中我們操作數據庫的時候經常會發生一個不該發生的問題:用戶意外的刪除一個非常重要的表或者是表中的數據而且沒有備份,需要盡快的恢復,以下就是解決的辦法:
主要是利用Oracle回收站的閃回特性oracle 回收站recyclebin是10g才有的新特性,當我們drop table cube_scope 【purge】時,如果不指定purge時,系統只是將這個表重命名為BIN$開頭的名稱,並在數據字典中修改了相關數據,表所占用的物理空間並沒有真正的回收,此時所占用的空間還是原來的表空間,當表空間不夠用時,ORACLE會跟據DROPSCN#自動進行逐個清理回收站中對像所占用的空間,10g默認是打開回收站功能的。
一、delete 數據 誤刪除
1、 刪除數據之后表結構沒有變化
直接使用表閃回,表閃回要求用戶必須要有flash any table權限
先確定刪除數據的時間(在刪除數據之前的時間就行,不過最好要具體到刪除數據的時間點)
alter table 表名 enable row movement //開啟行移動功能
flashback table 表名 to timestamp to_timestamp('刪除時間點','yyyy-mm-dd hh24:mi:ss')
//恢復數據到刪除時間點之前的狀態
Alter table 表名 disable row movement //關閉行移動功能(一定不能忘記)
2、 刪除數據之后表結構發生了變化
select * from 表名 as of timestamp to_timestamp('刪除時間點','yyyy-mm-dd hh24:mi:ss')
//找出被刪除的數據
insert into 表名 (select * from 表名 as of timestamp to_timestamp('刪除時間點','yyyy-mm-dd hh24:mi:ss')); //把刪除的數據重新插回原表,但注意主鍵不要重復
二 、drop命令 刪除表
由於oracle在刪除表時,沒有直接清空表所占的塊,oracle把這些已刪除的表的信息放到了一個虛擬容器“回收站”中,而只是對該表的數據塊做了可以被覆寫的標志,所以在塊未被重新使用前還可以恢復。
查看回收站中的表
select object_name,original_name,partition_name,type,ts_name,createtime,droptimefrom recyclebin;
可以看到被刪除的表在回收站被命名為’BIN$0z+2cCjdSjqkx1nsP/re7w==$0’
flashback table 原表名 to before drop (rename to 新表名) //閃回原表(重命名新表名)
或者
flashback table "回收站中的表名(如:BIN$0z+2cCjdSjqkx1nsP/re7w==$0)" to before drop (rename to 新表名) //用戶可能會經常多次創建和刪除同一個表就需要找到回收站的表名閃回相應的表版本
但是用這種方法只是把我們的表給找回來了,我們的索引和約束都沒有回來。所以我們一定要重新建立索引和約束。如果
oracle 閃回功能還可以閃回整個數據庫,使數據庫回到過去某一狀態。
alter database flashback on
flashback database to scn SCNNO; //使用SCN號閃回或者使用時間戳閃回
flashback database to timestamp to_timestamp('2007-10-25 12:00:00','yyyy-mm-dd hh24:mi:ss');
如果想要不經過回收站直接刪除並釋放所占空間
drop table 表名 purge //此命令相當於truncate+drop 操作,一般不建議這么做。
手工清除回收站中的對象。
prug table 表空間.表名 //清除具體的對象
prug tablespace 表空間 //清除指定的表空間對象
purge tablespace 表空間 user 用戶名 //刪除表空間指定用戶下的所有對像
purge recyclebin //刪除回收站
purge dba_recyclebin //刪除全體用戶在回收站的數據
ORACLE空間利用原則
1. 使用現有的表空間的未使用空間
2. 如果沒有了空閑空間,則檢查回收站,對於回收站的對象按照先進先出的原則,對於最先刪除的對象,oracle在空間不足之時會最先從回收站刪除以滿足新分配空間的需求
3. 如果回收站也沒有對象可以清理,則檢查表空間是否自擴展,如果自擴展則擴展表空間,然后分配新空間
4.如果表空間非自擴展,或者已經不能自擴展(到達最大限制),則直接報表空間不足錯誤,程序終止
* drop tablespace :會將recyclebin中所有屬於該tablespace的對像清除
* drop user :會將recyclebin中所有屬於該用戶的對像清除
* drop cluster : 會將recyclebin中所有屬於該cluster的成員對像清除
* drop type : 會將recyclebin中所有依賴該type對像清除
另外還需要注意一種情況,對像所在的表空間要有足夠的空間,不然就算drop掉經過recyclebin由於空間不足oracle會自動刪除的哦(切記)!
三、truncate刪除數據
1、使用閃回特性
因為truncate不是DML語句,是DDL語句,不能使用閃回查詢的方式恢復表數據,這里介紹一種通過flashback database(閃回整個數據庫)的方式恢復數據的方法。
在11g下,可以在mount和open模式來執行該命令
select status from v$instance; 查看數據庫模式
alter database open; //或者是mount
alter database flashback on
flashback database to timestamp to_timestamp('2007-10-25 12:00:00','yyyy-mm-dd hh24:mi:ss');
在執行完flashback database 命令之后,可以使用多種方式修復數據庫:
1). 直接alter database open resetlogs 打開數據庫,指定scn 或者timestamp 時間點之后產生的數據統統丟失。
2). 先執行alter database open read only 命令以read-only 模式打開數據庫,查看恢復后的數據是否滿足要求,如果滿足要求,則通過resetlogs打開數據庫,否則,重新執行flashback 操作。
3). 先執行alter database open read only 命令以read-only 模式打開數據庫,然后立刻通過邏輯導出的方式將誤操作涉及表的數據導出,再執行recover database 命令以重新應用數據庫產生的redo,將數據庫修復到flashback database 操作前的狀態,然后再通過邏輯導入的方式,將之前誤操作的表重新導入,這樣的話對現有數據的影響最小,不會有數據丟失。
這里演示第二種方法
alter
database
open
read
only;
查看數據是否符合要求不符合繼續
flashback database to timestamp to_timestamp
如果符合
startup mount force
;
alter
database
open
resetlog;
第三種方法
閃回之后 alter database open read only
exp 用戶名/用戶密碼 file=t.dmp tables=表名; //導出被truncate表的數據 如果不熟悉exp命令的話,可以去看exp/expdp 與 imp/impdp命令導入導出數據庫詳解
shutdown immediate //重啟數據庫恢復到閃回之前的時間點
startup mount;
recover database;
alter database open;
然后導入剛才導出的數據
imp 用戶名 /密碼 file=t.dmp tables=表名 ignore=y;