Oracle Find block in ASM

eric0435發表於2017-02-03

為了更容易的從ASM定位與抽取Oracle資料檔案,可以建立一個Perl指令碼find_block.pl來自動進行處理,只需要提供資料檔名與塊號。指令碼find_block.pl是一個Perl指令碼,它由dd或kfed命令組成。它可以與所有的Linux和Unix ASM版本與單例項的ASM或RAC環境中使用。

這個指令碼必須以ASM/Grid Infrastructure使用者來執行,在RAC環境中,指令碼可以在任何一個節點上執行,在執行指令碼之前,設定ASM環境變數並且確保ORACLE_SID,ORACLE_HOME,LD_LIBRARY_PATH等等設定正確。對於ASM 10g與11gr1來說,也可以設定環境變數PERL5LIB,比如:

export PERL5LIB=$ORACLE_HOME/perl/lib/5.8.3:$ORACLE_HOME/perl/lib/site_perl

執行指令碼例子如下:

$ORACLE_HOME/perl/bin/perl find_block.pl filename block

命令中的filename是指要抽取的資料塊所在檔案的檔名。對於資料檔案,檔名可以透過在資料庫例項上執行select name from v$datafile來獲得。block是要從ASM中抽取資料塊的塊號

輸出結果類似如:

dd if=[ASM disk path] ... of=block_N.dd

或Exadata中的

kfed read dev=[ASM disk path] ... > block_N.txt

如果磁碟組是外部冗餘,這個指令碼將生成單個命令。對於normal冗餘磁碟組檔案來說,這個指令碼將生成兩個命令,對於high冗餘磁碟組檔案來說,這個指令碼將生成三個命令。

下面將對於oracle 10g rac來透過find_block.pl腳來從ASM中抽取資料塊

SQL> select name from v$tablespace;

NAME
------------------------------
SYSTEM
UNDOTBS1
SYSAUX
USERS
TEMP
EXAMPLE
UNDOTBS2
YB
TEST

9 rows selected.

SQL> create table t1 (name varchar2(16)) tablespace TEST;

Table created.

SQL> insert into t1 values ('CAT');

1 row created.

SQL> insert into t1 values ('DOG');

1 row created.

SQL> commit;

Commit complete.

SQL> select rowid,name from t1;

ROWID              NAME
------------------ ----------------
AAAN8qAAIAAAAAUAAA CAT
AAAN8qAAIAAAAAUAAB DOG

SQL> select dbms_rowid.rowid_block_number('AAAN8qAAIAAAAAUAAA') "block" from dual;

     block
----------
        20

SQL> select t.name "Tablespace", f.name "Datafile" from v$tablespace t, v$datafile f where t.ts#=f.ts# and t.name='TEST';

Tablespace                     Datafile
------------------------------ --------------------------------------------------
TEST                           +DATADG/test/datafile/test.269.930512093

切換到ASM環境,設定PERL5LIB,執行指令碼

[oracle@jyrac3 bin]$ export ORACLE_SID=+ASM1
[oracle@jyrac3 bin]$ export PERL5LIB=$ORACLE_HOME/perl/lib/5.8.3:$ORACLE_HOME/perl/lib/site_perl

[oracle@jyrac3 bin]$ $ORACLE_HOME/perl/bin/perl find_block.pl +DATADG/test/datafile/test.269.930512093 20
dd if=/dev/raw/raw3 bs=8192 count=1 skip=266260 of=block_20.dd
dd if=/dev/raw/raw4 bs=8192 count=1 skip=266260 of=block_20.dd

從上面的輸出可以看到指定的檔案是normal冗餘,指令碼生成了兩個dd命令,下面我們來執行:

[root@jyrac3 ~]# dd if=/dev/raw/raw3 bs=8192 count=1 skip=266260 of=block_20.dd
1+0 records in
1+0 records out
8192 bytes (8.2 kB) copied, 0.00608323 seconds, 1.3 MB/s

下面檢視block_20.dd檔案的內容,使用od工具,我們可以看到插入表中的資料:

[root@jyrac3 ~]# od -c block_20.dd | tail -3
0017740   S   O   R   T   =   '   B   I   N   A   R   Y   '  \b   , 001
0017760 001 003   D   O   G   , 001 001 003   C   A   T 001 006  \r 203
0020000

可以看到DOG與CAT

Example with ASM version 12.1.0.1 in Exadata
在Exadata中,不可以使用dd命令來抽取資料塊,因為磁碟對資料庫伺服器不可見。為了得到資料庫的資料塊,可以使用kfed工具,因為find_block.pl將由kfed命令組成。

$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.1.0 Production on [date]

SQL> alter pluggable database BR_PDB open;

Pluggable database altered.

SQL> show pdbs

CON_ID CON_NAME OPEN MODE   RESTRICTED
------ -------- ----------- ----------
       2 PDB$SEED READ ONLY   NO
...
       5 BR_PDB   READ WRITE  NO

SQL>

$ sqlplus bane/welcome1@BR_PDB

SQL*Plus: Release 12.1.0.1.0 Production on [date]

SQL> create table TAB1 (n number, name varchar2(16)) tablespace USERS;

Table created.

SQL> insert into TAB1 values (1, 'CAT');

1 row created.

SQL> insert into TAB1 values (2, 'DOG');

1 row created.

SQL> commit;

Commit complete.

SQL> select t.name "Tablespace", f.name "Datafile"
from v$tablespace t, v$datafile f
where t.ts#=f.ts# and t.name='USERS';

Tablespace Datafile
---------- ---------------------------------------------
USERS      +DATA/CDB/054.../DATAFILE/users.588.860861901

SQL> select ROWID, NAME from TAB1;

ROWID              NAME
------------------ ----
AAAWYEABfAAAACDAAA CAT
AAAWYEABfAAAACDAAB DOG

SQL> select DBMS_ROWID.ROWID_BLOCK_NUMBER('AAAWYEABfAAAACDAAA') "Block number" from dual;

Block number
------------
       131

SQL>

切換到ASM環境執行指令碼

$ $ORACLE_HOME/perl/bin/perl find_block.pl +DATA/CDB/0548068A10AB14DEE053E273BB0A46D1/DATAFILE/users.588.860861901 131
kfed read dev=o/192.168.1.9/DATA_CD_03_exacelmel05 ausz=4194304 aunum=16212 blksz=8192 blknum=131 | grep -iv ^kf > block_131.txt
kfed read dev=o/192.168.1.11/DATA_CD_09_exacelmel07 ausz=4194304 aunum=16267 blksz=8192 blknum=131 | grep -iv ^kf > block_131.txt

注意find_block.pl將生成兩個指令碼,資料檔案是normal冗餘,執行以下命令:

$ kfed read dev=o/192.168.1.9/DATA_CD_03_exacelmel05 ausz=4194304 aunum=16212 blksz=8192 blknum=131 | grep -iv ^kf > block_131.txt
$

檢查block_131檔案的內容,可以看到DOG與CAT

$ more block_131.txt
...
FD5106080 00000000 00000000 ...  [................]
      Repeat 501 times
FD5107FE0 00000000 00000000 ...  [........,......D]
FD5107FF0 012C474F 02C10202 ...  [OG,......CAT..,-]
$

Find any block
find_block.pl指令碼可以用來從儲存在ASM中的任何檔案抽取資料塊。執行下面的命令來抽取控制檔案與隨機資料塊

$ $ORACLE_HOME/perl/bin/perl find_block.pl +DATA/CDB/CONTROLFILE/current.289.843047837 5
kfed read dev=o/192.168.1.9/DATA_CD_10_exacelmel05 ausz=4194304 aunum=73 blksz=16384 blknum=5 | grep -iv ^kf > block_5.txt
kfed read dev=o/192.168.1.11/DATA_CD_01_exacelmel07 ausz=4194304 aunum=66 blksz=16384 blknum=5 | grep -iv ^kf > block_5.txt
kfed read dev=o/192.168.1.10/DATA_CD_04_exacelmel06 ausz=4194304 aunum=78 blksz=16384 blknum=5 | grep -iv ^kf > block_5.txt
$

可以看到指令碼顯示了正確的控制檔案塊大小(16K),並且生成三個不同的命令。當磁碟組data是normal冗餘磁碟組時,控制檔案會為high冗餘(ASM中控制檔案預設為冗餘)。

小結:
find_block.pl是perl指令碼,它由dd或kfed命令組成用來從ASM中的檔案中抽取資料塊。在大多數情況下我們想要從資料檔案中抽取資料塊,但指令碼也能從控制檔案,重做日誌或任何其它檔案中抽取資料塊。

如果檔案儲存在外部冗餘磁碟組中,那麼指令碼將會生成單個命令,這可以用來從ASM磁碟中抽取資料塊。

如果檔案儲存在normal冗餘磁碟組,那麼指令碼將會生成兩個命令,它們用來從兩個不同的ASM磁碟來抽取資料塊(相同副本)。

如果檔案儲存在high冗餘磁碟組,那麼指令碼將會生成三個命令。

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

相關文章