[20210319]bbed讀取資料塊3.txt

lfree發表於2021-03-19

[20210319]bbed讀取資料塊3.txt

--//昨天做了bbed讀取資料塊連結:http://blog.itpub.net/267265/viewspace-2763810/
--//今天測試一些特殊情況使用它恢復會出現什麼情況,算是做一些補充。
--//注意不要拿它到生產系統測試:

1.環境:
SCOTT@book> @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

--//drop table t purge ;

SCOTT@book> create table t as select * from all_objects where rownum<=1000;
Table created.

SCOTT@book> select object_id,data_object_id from dba_objects where owner=user and object_name='T';
 OBJECT_ID DATA_OBJECT_ID
---------- --------------
     90982          90982

SCOTT@book> select rowid from t where rownum=1;
ROWID
------------------
AAAWNmAAEAAAALbAAA

SCOTT@book> @ rowid AAAWNmAAEAAAALbAAA
    OBJECT       FILE      BLOCK        ROW ROWID_DBA            DBA                  TEXT
---------- ---------- ---------- ---------- -------------------- -------------------- ----------------------------------------
     90982          4        731          0  0x10002DB           4,731                alter system dump datafile 4 block 731 ;

SCOTT@book> @ bbedcol scott t
DISPLAY BBED EXAMINE(X) FORMAT
C80
---------------
cccnncttcccccnc
    
2.建立指令碼,測試讀取看看。
--//註指令碼做一些修改,增加bbed /x 的格式,程式碼更加通用一些,注意我沒有做引數檢查。

$ cat fff.sh
#! /bin/bash -x
# argv1=file_number argv2=begin_block argvs3=end_block argv4=data_object_id argv5=bbed /x format
file_number=$1
begin_block=$2
end_block=$3
data_object_id=$4
ff="/r"${5}

# scan1 begin_block to end_block,define Scope.
/bin/rm scan1.txt
while [ $begin_block -le $end_block ]
do
        v_object_id=$(echo "p /d dba $file_number,$begin_block  ktbbh.ktbbhsid.ktbbhod1" | rlbbed | grep ktbbhod1 |awk '{print $NF}')
        if [ -z "$v_object_id" ]
        then
                v_object_id=0
        fi

        if (( $v_object_id == $data_object_id ))
        then
                echo $file_number,$begin_block >> scan1.txt
        fi
        begin_block=$[ begin_block + 1 ]
done

# scan2 kdbr and display record.

cat scan1.txt |while read dba
do
        #echo set dba $dba
        kdbr_size=$(echo map dba $dba | rlbbed | grep "sb2 kdbr" | sed -e "s/^.*\[//;s/].*$//")
        #echo $kdbr_size

        begin=0
        end=$[ kdbr_size -1 ]
        #echo $begin $end

        while [ $begin -le $end ]
        do
                kdbr_off=$(echo p dba $dba offset 0 kdbr | rlbbed | grep "sb2 kdbr\[$begin\]" | awk '{print $NF'})
                #echo $kdbr_off
                #if [ $kdbr_off -gt $kdbr_size ]
                if (( $kdbr_off > $kdbr_size ))
                then
                        echo -n "x $ff dba $dba *kdbr[$begin]" | rlbbed  | grep "^col " | cut -c20- |  paste -sd'|'
                fi
                begin=$[ begin + 1 ]
        done
done

3.恢復看看:
$ . fff.sh 4 731 800 90982 cccnncttcccccnc |wc
   1000    6944  119676

--//不做匯入測試了。
--//使用toad匯入
--//整理本文如下,使用vim的替換功能:
--//:%s+ |+|+g
--//:%s+ $++g
--//:%s+|\*NULL\*|++g

4.增加一些難度:
SCOTT@book> delete from t where mod(object_id,100)=0;
9 rows deleted.

SCOTT@book> commit ;
Commit complete.

SCOTT@book> alter system checkpoint ;
System altered.
--//注:不寫盤恢復看不到改變。

$ . fff.sh 4 731 800 90982 cccnncttcccccnc >| laji.txt

--//開啟laji.txt文字發現:
  98 SYS|EDITION$|*NULL*|99 |99 |TABLE|2013-08-24 11:37:36 |2013-08-24 11:37:36 |2013-08-24:11:37:36|VALID|N|N|N|1
  99
 100 SYS|FIXED_OBJ$|*NULL*|101 |101 |TABLE|2013-08-24 11:37:36 |2013-08-24 11:37:36 |2013-08-24:11:37:36|VALID|N|N|N|1

--//刪除的記錄顯示為空行,這個問題都不是很大,指令碼可以處理掉,也可以透過vim編輯去掉或者grep過濾。
--//做一個update看看行遷移會出現什麼情況。

SCOTT@book> update t set owner=lpad('A',30,'A') where DBMS_ROWID.ROWID_BLOCK_NUMBER (rowid)=731;
88 rows updated.

SCOTT@book> commit ;
Commit complete.

SCOTT@book> alter system checkpoint ;
System altered.

$ . fff.sh 4 731 731 90982 cccnncttcccccnc >| laji.txt
--//開啟laji.txt文字發現:
 32 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|I_COL2|*NULL*|49 |49 |INDEX|2013-08-24 11:37:35 |2013-08-24 11:37:35 |2013-08-24:11:37:35|VALID|N|N|N|4
 33
 34 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|I_OBJ4|*NULL*|39 |39 |INDEX|2013-08-24 11:37:35 |2013-08-24 11:37:35 |2013-08-24:11:37:35|VALID|N|N|N|4

BBED> x /rcccnncttcccccnc dba 4,731 *kdbr[32]
rowdata[4396]                               @4781
-------------
flag@4781: 0x20 (KDRHFH)
lock@4782: 0x02
cols@4783:    0
nrid@4784:0x010002fd.0
--//出現行遷移,麻煩的是如果部分內容在塊中,另外的資料在另外塊中,使用bbed恢復難度更大。
--//0x010002fd = set dba 4,765 = alter system dump datafile 4 block 765 = 16777981
--//真實的資料在dba=4,765.

BBED> x /rcccnncttcccccnc dba 4,765 *kdbr[0]
rowdata[1692]                               @8077
-------------
flag@8077: 0x0c (KDRHFL, KDRHFF)
lock@8078: 0x01
cols@8079:   14
hrid@8080:0x010002db.20

col   0[30] @8086: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
col    1[6] @8117: I_OBJ2
col    2[0] @8124: *NULL*
col    3[2] @8125: 37
col    4[2] @8128: 37
col    5[5] @8131: INDEX
col    6[7] @8137: 2013-08-24 11:37:35
col    7[7] @8145: 2013-08-24 11:37:35
col   8[19] @8153: 2013-08-24:11:37:35
col    9[5] @8173: VALID
col   10[1] @8179: N
col   11[1] @8181: N
col   12[1] @8183: N
col   13[2] @8185: 4

$ . fff.sh 4 765 765 90982 cccnncttcccccnc | grep I_OBJ2
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|I_OBJ2|*NULL*|37 |37 |INDEX|2013-08-24 11:37:35 |2013-08-24 11:37:35 |2013-08-24:11:37:35|VALID|N|N|N|4
--//在另外的塊中可以看到完整記錄。

$ . fff.sh 4 731 800 90982 cccnncttcccccnc | grep "^[A-Z]" | wc
    991    6883  120845

$ . fff.sh 4 731 800 90982 cccnncttcccccnc | grep -v "^$" |wc
    991    6883  120845
    
--// 1000-9  = 991,可以發現我的測試恢復沒有丟失資料,因為發生行遷移是整體遷移,出現行連結bbed就比較麻煩。

5.總結:
--//不是很實用,如果delete記錄,輸出會出現空行。而且記錄多,處理起來很慢。
--//無法解決行連結和行遷移問題。
--//另外有人問如果truncate後如何知道以前的DATA_OBJECT_ID。你可以找靠近段頭的塊,做一個轉儲就知道。
--//我記憶裡logminer也能找到原來的DATA_OBJECT_ID。也可以使用as of timestamp方式檢視使用sys使用者檢視,
--//不知道12c以上是否可行。

SCOTT@book> select sysdate from dual;
SYSDATE
-------------------
2021-03-19 16:25:44

SCOTT@book> truncate table t;
Table truncated.

SCOTT@book> select object_id,data_object_id from dba_objects where owner=user and object_name='T';
 OBJECT_ID DATA_OBJECT_ID
---------- --------------
     90982          90984

SYS@book> select object_id,data_object_id from dba_objects as of timestamp to_date('2021-03-19 16:25:44','yyyy-mm-dd hh24:mi:ss') where owner='SCOTT' and object_name='T';

 OBJECT_ID DATA_OBJECT_ID
---------- --------------
     90982          90982
--//再次宣告千萬別在生產系統做這樣的測試!!

6.附上bbedcol指令碼語句:
$ cat bbedcol12.sql
prompt
PROMPT DISPLAY BBED EXAMINE(X) FORMAT
prompt

SELECT REPLACE (LISTAGG (c1, ',') WITHIN GROUP (ORDER BY column_id), ',') c80
  FROM (  SELECT data_type
                ,column_id
                ,column_name
                ,DECODE
                 (
                    data_type
                   ,'NUMBER', 'n'
                   ,'CHAR', 'c'
                   ,'VARCHAR', 'c'
                   ,'VARCHAR2', 'c'
                   ,'DATE', 't'
                   ,' '
                 )
                    c1
            FROM dba_tab_cols
           WHERE     owner = UPPER (NVL ('&1', USER))
                 AND TABLE_NAME = UPPER ('&2')
                 AND hidden_column = 'NO'
        ORDER BY SEGMENT_COLUMN_ID);


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/267265/viewspace-2763861/,如需轉載,請註明出處,否則將追究法律責任。

相關文章