[20170410]快速找回触发器内容2.txt
--上午登录发现一个是触发器被人为删除了,需要恢复.链接http://www.itpub.net/thread-2084789-1-1.html.
--我提供几个方法:1.取出备份的system数据文件,通过bbed之类的工具定位.2使用logminer 应该也可以定位,表sys.source$.
--实际上还有1个简单粗暴的方法,直接通过strings查询归档日志.链接:
http://blog.itpub.net/267265/viewspace-2136894/
--如果sys.source$里面删除的数据没有覆盖,我觉得正常的业务数据库不大可能经常改动这个表,可以通过bbed来恢复内容。
--测试例子:
1.环境:
SYS@book> @ &r/ver1
PORT_STRING VERSION BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx 11.2.0.4.0 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
CREATE OR REPLACE FUNCTION SCOTT.sleep (seconds IN NUMBER)
RETURN NUMBER AS
BEGIN
sys.dbms_lock.sleep(seconds);
RETURN seconds;
END;
/
2.假设删除了如何恢复呢?
SYS@book> drop function scott.sleep ;
Function dropped.
--//定位在那个块(最好选择特殊的字符,这样定位准确一些)
$ strings -3 -t d /mnt/ramdisk/book/system01.dbf | grep -i sys.dbms_lock.sleep;
495150716 +begin sys.dbms_lock.sleep(seconds=>?); end;
751757758 sys.dbms_lock.sleep(seconds);
SYS@book> select 751757758/8192 from dual ;
751757758/8192
--------------
91767.3044
3.bbed恢复:
--//注意最好不要在原文件操作,可以先拷贝一份在这个文件操作。
BBED> set dba 1,91767
DBA 0x00416677 (4286071 1,91767)
BBED> map /v
...
sb2 kdbr[99] @110
--//存在99条记录。
--//编辑文件c.cmd
set dba 1,91767
x /rnnc *kdbr[0]
...
x /rnnc *kdbr[98]
quit
$ cat bbed.par
blocksize=8192
listfile=$HOME/bbed/filelist.txt
mode=edit
PASSWORD=blockedit
SPOOL=Y
$ $ORACLE_HOME/bin/bbed parfile=bbed.par cmdfile=c.cmd
--//这样全部操作记录在log.bbd文件中。
$ grep -B3 ": 0x3c (" log.bbd
BBED> x /rnnc *kdbr[23]
rowdata[0] @2383
----------
flag@2383: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)
--
BBED> x /rnnc *kdbr[24]
rowdata[53] @2436
-----------
flag@2436: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)
--
BBED> x /rnnc *kdbr[25]
rowdata[82] @2465
-----------
flag@2465: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)
--
BBED> x /rnnc *kdbr[26]
rowdata[100] @2483
------------
flag@2483: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)
--
BBED> x /rnnc *kdbr[27]
rowdata[144] @2527
------------
flag@2527: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)
--
BBED> x /rnnc *kdbr[28]
rowdata[174] @2557
------------
flag@2557: 0x3c (KDRHFL, KDRHFF, KDRHFD, KDRHFH)
--//基本可以确定删除记录在行记录是23,24,25,26,27,28.
assign dba 1,91767 offset 2383 = 0x2c <=手工拷贝和粘贴第一行要确认1次。
assign dba 1,91767 offset 2436 = 0x2c
assign dba 1,91767 offset 2465 = 0x2c
assign dba 1,91767 offset 2483 = 0x2c
assign dba 1,91767 offset 2527 = 0x2c
assign dba 1,91767 offset 2557 = 0x2c
BBED> x /6rnnc *kdbr[23]
rowdata[0] @2383
----------
flag@2383: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@2384: 0x02
cols@2385: 3
col 0[4] @2386: 90510
col 1[2] @2391: 1
col 2[41] @2394: FUNCTION sleep (seconds IN NUMBER).
rowdata[53] @2436
-----------
flag@2436: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@2437: 0x02
cols@2438: 3
col 0[4] @2439: 90510
col 1[2] @2444: 2
col 2[17] @2447: RETURN NUMBER AS.
rowdata[82] @2465
-----------
flag@2465: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@2466: 0x02
cols@2467: 3
col 0[4] @2468: 90510
col 1[2] @2473: 3
col 2[6] @2476: BEGIN.
rowdata[100] @2483
------------
flag@2483: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@2484: 0x02
cols@2485: 3
col 0[4] @2486: 90510
col 1[2] @2491: 4
col 2[32] @2494: sys.dbms_lock.sleep(seconds);.
rowdata[144] @2527
------------
flag@2527: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@2528: 0x02
cols@2529: 3
col 0[4] @2530: 90510
col 1[2] @2535: 5
col 2[18] @2538: RETURN seconds;.
rowdata[174] @2557
------------
flag@2557: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@2558: 0x02
cols@2559: 3
col 0[4] @2560: 90510
col 1[2] @2565: 6
col 2[4] @2568: END;
--//ok这样已经恢复。
$ grep "col *2\[" log.bbd
col 2[41] @2394: FUNCTION sleep (seconds IN NUMBER).
col 2[17] @2447: RETURN NUMBER AS.
col 2[6] @2476: BEGIN.
col 2[32] @2494: sys.dbms_lock.sleep(seconds);.
col 2[18] @2538: RETURN seconds;.
col 2[4] @2568: END;
--//再编辑输出,删除前面字符,后面的.就ok了,当然我的测试删除函数很小,大的函数或者过程如果跨块就复杂了。
--//仅仅提供思路,实际上就是使用bbed恢复删除数据文件的思路。
--//另外我个人不建议修改system数据文件,取出再重新建立就ok了。