[原]記一次使用flashback恢復數據,警惕自己不要浮躁,還是太嫩了
周五晚十點多,同事突然來電稱操作CMS后臺的時候不小心刪除了很多記錄(其實應該是這個CMS的邏輯問題),大概了解了情況以后,能初步判斷為p_web表的2萬多條數據被delete了,事發時間大概在9:30左右,這種場景幾乎就是“專門”為flashback而設的了。
于是馬上翻開書找到flashback那節書,先鄙視一下自己,以前所學的都還給書本了。
確認一下可以flashback的極限是多少
select
min(start_timestamp)
from
flashback_transaction_query
where
table_name='P_WEB'
and table_owner='CMS'
結果是前天的下午3點,比預期中的時間要長很多啊。
由于p_web表數據量不大,還不到100M,趕緊做個“備份”,免得突然犯渾把剩下的2萬多條記錄都整丟了,那就可以跳樓了:
create table p_web_bad as select * from p_web;
使用flashback query將9:20的數據放在一個p_web_20100507_0920表里面,讓同事看看效果先:
create table p_web_20100507_0920
as
select
*
from
p_web
as of timestamp to_date('2010-05-07 21:20:00','yyyy-mm-dd hh24:mi:ss');
其實我也是笨,脫離了表現層的數據能看出什么呢?除了“感覺”上是正確的一點說服力也沒有。
同事說這個數據沒問題。為了進一步確定事發的準確時間點,使用flashback transaction query 將自8:30以來的所有undo操作列出,這樣可以找出什么時候開始刪除的了。
create table p_web_undo_20100507_2030
as
select
start_timestamp,operation,undo_sql
from
flashback_transaction_query
where
table_name='P_WEB'
and table_owner='CMS'
and start_timestamp>to_date('2010-05-07 20:30:00','yyyy-mm-dd hh24:mi:ss')
order by
start_timestamp desc
經過一個簡單的查詢從start_timestamp 能查出是21:39:04開始刪除的,只要將flashback到21:38:00問題就OK了啦。
flashback table p_web
to timestamp to_date('2010-05-07 21:38:00','yyyy-mm-dd hh24:mi:ss');
此時,報了一個錯:
ORA-08189: cannot flashback the table because row movement is not enabled
小問題,enable row movement 就是了
alter table p_web enable row movement;
我再閃(flashback):
flashback table p_web
to timestamp to_date('2010-05-07 21:38:00','yyyy-mm-dd hh24:mi:ss');
shit!竟然出現了flashback的克星:
ora-01555 snapshot too old
明明前面查到可以flashback的時間很長的啊,莫非是前面幾個大create table把undo內容刷走了,這也太快了吧@_@!
先不管了,我同事還在著急的等待,雖然沒有催我,但是“弄丟”數據的心情我很清楚。
幸好前面創建了一個p_web_undo_20100507_2030表,里面有一對undo的sql,可以將被delete的數據再insert回去。
于是寫了個簡單的過程做這件事:
declare
v_undo_sql varchar2(4000);
CURSOR cur is select substr(undo_sql,1,length(undo_sql)-1) --將undo_sql最后那個分號去掉
from p_web_undo_20100507_2030 where operation='DELETE';
BEGIN
open cur;
loop
fetch cur into v_undo_sql;
EXIT when cur%NOTFOUND;
execute immediate v_undo_sql;
--dbms_output.put_line(v_undo_sql);
END LOOP;
CLOSE cur;
END delete_state ;
經過“漫長”的等待,終于將誤刪的數據恢復回來了。
經過這次數據恢復讓我認識到:
1。雖然掌握了基本概念,但是熟練程度還不夠,體現在臨急翻書上。
2。實際操作經驗欠缺,整個過程實際上沒多少東西,但是卻足足折騰了一個半小時。
3。前瞻性不足,這個數據庫是我維護的,對于誤操作刪除數據這種問題應該要有所覺悟,就這個問題而言,我做的措施僅僅是擴大了undo表空間。
總的來說,就是太嫩了。
浙公網安備 33010602011771號