행위

"오라클 블럭 덤프"의 두 판 사이의 차이

DB CAFE

(덤프 방법)
 
(같은 사용자의 중간 판 25개는 보이지 않습니다)
5번째 줄: 5번째 줄:
  
 
=== 덤프 방법 ===
 
=== 덤프 방법 ===
* 프로세스 A 가 test 라는 이름의 테이블의 특정 로우를 다음과 같이 변경
+
 
 +
[1단계] 테스트 테이블 생성 후 데이터 1건 입력
 +
<source lang=sql>CREATE TABLE TB_TEST
 +
  ( A NUMBER,
 +
B VARCHAR2(10)
 +
  )
 +
;
 +
 
 +
-- 데이터 1건 입력
 +
INSERT INTO TB_TEST VALUES (1,'11');
 +
commit;
 +
</source>
 +
 
 +
 
 +
[2단계] TB_TEST 테이블의 특정 로우를 다음과 같이 변경
 +
<source lang=sql>-- 데이터 변경 (A컬럼 값 1를 2로 변경 )
 +
SQL> update TB_TEST set A = 2 where rownum = 1;
 +
</source>
 +
 
 +
 
 +
[3단계] Update가 이루어진 로우의 위치를 DBMS_ROWID 패키지를 이용하여 찾을수 있다.
 +
<source lang=sql>SQL>select rowid
 +
        , dbms_rowid.rowid_relative_fno(rowid) as file_no
 +
        , dbms_rowid.rowid_block_number(rowid) as block_no
 +
from TB_TEST where rownum = 1;
 +
</source>
 +
 
 
<source lang=sql>
 
<source lang=sql>
SQL> update test set id = 1 where rownum = 1;
+
ROWID              FILE_NO    BLOCK_NO
 +
------------------ ---------- ----------
 +
AAASk/AAHAAAALcAAA 7 732
 
</source>
 
</source>
- Update가 이루어진 로우의 위치를 DBMS_ROWID 패키지를 이용해서 얻는다.
 
  
 +
* 변경된 로우가 위치한 블록 주소는 데이터 파일번호가 7번, 블록번호가 732번임을 확인.
 +
 +
[4단계] 이제 이 값을 이용해 해당 데이터 블록을 덤프 할 수 있다.
 
<source lang=sql>
 
<source lang=sql>
SQL>select rowid
+
-- 트레이스 파일 식별자 설정 (트레이스파일을 쉽게 찾기 위해서 설정 )
        , dbms_rowid.rowid_relative_fno(rowid) as fno
+
alter session set tracefile_identifier ='DBCAFE_Block_dump';
        , dbms_rowid.rowid_block_number(rowid) as blkno
 
from test where rownum = 1;
 
 
</source>
 
</source>
 +
 
<source lang=sql>
 
<source lang=sql>
ROWID FNO BLKNO
+
SQL> alter system dump datafile 7 block 732
------------------ ---------- ----------
 
AAAMZqAABAAANoKAAA 1 55818
 
 
</source>
 
</source>
  
- 변경된 로우가 위치한 블록 주소는 파일번호가 1번, 블록번호가 55818번에 해당한다.
+
- trace 파일 위치로 이동
- 이 값을 이용해 해당 데이터 블록을 다음과 같이 덤프할 수 있다.
 
 
<source lang=sql>
 
<source lang=sql>
SQL> alter system dump datafile 1 block 55818
+
-- sqlplus 에서 쉘상태로 나오기
 +
SQL>!
 +
 
 +
-- 트레이스 폴더로 이동
 +
cd $ORACE_BASE/diag/rdbms/{mongo/MONGO}/trace -- DB마다 {---} 위치가 다름
 +
 
 +
-- 트레이스 파일 찾기
 +
ls |grep DBCAFE_Block_dump;
 +
 
 +
MONGO_ora_43565_DBCAFE_Block_dump.trc <== 트레이스 파일
 +
MONGO_ora_43565_DBCAFE_Block_dump.trm
 +
 
 +
-- 트레이스 파일 열기
 +
vi MONGO_ora_43565_DBCAFE_Block_dump.trc
 
</source>
 
</source>
 +
 
<source lang=sql>
 
<source lang=sql>
Start dump data blocks tsn: 0 file#: 1 minblk 55818 maxblk 55818
+
Trace file /u01/app/oracle/diag/rdbms/mongo/MONGO/trace/MONGO_ora_43565_DBCAFE_Block_dump.trc
buffer tsn: 0 rdba: 0x0040da0a (1/55818)
+
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
scn: 0x0000.02ec5e30 seq: 0x02 flg: 0x02 tail: 0x5e300602
+
Version 19.3.0.0.0
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
+
...... 중략 ....
Block header dump: 0x0040da0a
 
Object id on Block Y
 
seg/obj: 0xc66a csc: 0x00.2ec5e34 itc: 2 flg: - typ: 1 - DATA
 
fsl: 0 fnx: 0x0 ver: 0x01
 
  
Itl Xid Uba Flag Lck Scn/Fsc
+
block_row_dump:
0x01 0x0016.026.00003222 0x01c0003f.0410.26 ---- 1 fsc …
+
tab 0, row 0, @0x1f86
0x02 0x0016.025.00003222 0x01c0003f.0410.25 C--- 0 scn …
+
tl: 9 fb: --H-FL-- lb: 0x2  cc: 2
ITL 정보
+
col 0: [ 2] c1 03
data_block_dump,data header at 0x862025c
+
col 1: [ 2] 31 31
===============
+
 
tsiz: 0x1fa0
+
..... 중략 ......
hsiz: 0x20
+
 
pbl: 0x0862025c
+
block_row_dump:
bdba: 0x0040da0a
+
tab 0, row 0, @0x1f86
76543210
+
tl: 9 fb: --H-FL-- lb: 0x1  cc: 2
flag=--------
+
col 0: [ 2] c1 02
ntab=1
+
col 1: [ 2] 31 31
nrow=7
+
end_of_block_dump
...
+
Block dump from disk:
block_row_dump: Row 데이터 정보
+
buffer tsn: 4 rdba: 0x01c002dc (7/732)
tab 0, row 0, @0x13cd
+
scn: 0x5de721 seq: 0x02 flg: 0x06 tail: 0xe7210602
tl: 1009 fb: --H-FL-- lb: 0x1 cc: 2 로우에 Lock Byte 정보가 있음
+
frmt: 0x02 chkval: 0xdfd5 type: 0x06=trans data
col 0: [ 2] c1 02
+
..... 생략 ...
col 1: [1000]
 
31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
 
...
 
tab 0, row 1, @0xfdc
 
tl: 1009 fb: --H-FL-- lb: 0x0 cc: 2
 
col 0: [ 2] c1 03
 
col 1: [1000]
 
31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
 
...
 
 
</source>
 
</source>
  
* 블록 덤프 파일의 내용을 통해 다음과 같은 사실을 확인할 수 있다.
+
{{틀:고지상자
 
+
|제목 = 블록 덤프 파일의 내용을 통해 다음과 같은 사실을 확인할 수 있다.
# ITL (Interested Transaction List)에 로우를 변경한 트랜잭션이 itl=0x01로 등록되어있다.  
+
|내용 =# ITL (Interested Transaction List)에 로우를 변경한 트랜잭션이 itl=0x01로 등록되어있다.  
 
# 현재 상태는 아직 커밋되지 않은 액티브(Active) 상태이며, 따라서 TX 락을 획득하고 있다.  
 
# 현재 상태는 아직 커밋되지 않은 액티브(Active) 상태이며, 따라서 TX 락을 획득하고 있다.  
 
# Xid = 0x0016.026.00003222 인데 이 값을 십진수로 변환하면 USN=22, SLOT=38, SQN=12384가 된다.  
 
# Xid = 0x0016.026.00003222 인데 이 값을 십진수로 변환하면 USN=22, SLOT=38, SQN=12384가 된다.  
83번째 줄: 110번째 줄:
 
22 38 12834 XID = USN + SLOT + SQN
 
22 38 12834 XID = USN + SLOT + SQN
 
</source>
 
</source>
 
+
}}
  
 
2) ITL 정보에서 Lock = 1 인데, 이것은 Transaction에 의해 변경된 로우수를 의미  
 
2) ITL 정보에서 Lock = 1 인데, 이것은 Transaction에 의해 변경된 로우수를 의미  
112번째 줄: 139번째 줄:
 
: 심지어 오라클 매뉴얼에서도 애매모호한 표현으로 설명되어 있다.  
 
: 심지어 오라클 매뉴얼에서도 애매모호한 표현으로 설명되어 있다.  
 
: 로우 레벨 락은 TX 락을 이용해 구현되지만 TX 락 자체가 로우 레벨 락은 아니며, 다양한 정보들이 조합되어 로우 레벨 락이 구현된다.
 
: 로우 레벨 락은 TX 락을 이용해 구현되지만 TX 락 자체가 로우 레벨 락은 아니며, 다양한 정보들이 조합되어 로우 레벨 락이 구현된다.
 +
 +
=== 블럭 덤프 실습 ===
 +
==== Dumping Oracle Database Blocks ====
 +
 +
As we already know the data in oracle database resides in Tablespace (Logical Container) and each Tablespace has one or more datafile (Physical storage) so lets start with this
 +
 +
===== [1 단계] Create a tablespace =====
 +
<source lang=sql>
 +
SQL> create tablespace TS_DBCAFE_01
 +
              datafile '/u01/dbatest1/stage/database/db01.dbf' size 100M;
 +
 +
Tablespace created.
 +
</source>
 +
 +
===== [2단계] Find the Detail of your Tablespace and Datafile =====
 +
<source lang=sql>
 +
SQL> select f.FILE#
 +
          , f.NAME "File"
 +
          , t.NAME "Tablespace"
 +
      from V$DATAFILE f
 +
          , V$TABLESPACE t
 +
      where t.NAME='TS_DBCAFE_01'
 +
        and f.TS# = t.TS#;
 +
 +
    FILE# File                                                        Tablespace
 +
---------- ------------------------------------------------------------ ---------------
 +
        27 /u01/dbatest1/stage/database/db01.dbf                        TEST_AU_OS
 +
</source>
 +
 +
===== [3 단계] Table 생성 후 테스트 데이터 입력 =====
 +
<source lang=sql>
 +
SQL> create table test (n number, name varchar2(16))
 +
tablespace TS_DBCAFE_01;
 +
Table created.
 +
SQL> insert into test values (1,'TEST');
 +
1 row created.
 +
SQL> commit;
 +
Commit complete.
 +
</source>
 +
At this point we know that my data is stored in a table called "TEST" which is stored in a Tablespace called "TEST_AU_OS" and data physically in a datafile  /u01/dbatest1/stage/database/db01.dbf which belongs to "TEST_AU_OS" tablespace
 +
Datafile is constructed with database blocks or in other words the space to a datafile is allocated in terms of data blocks( standard DB Block Size is 8K). So let us find out the DB Block Size and Actual Block number which hold my piece of data
 +
 +
===== [4단계] DB Block Size 조회 및 Block Number 조회 =====
 +
<source lang=sql>
 +
SQL> select ROWID,n,name from test where n=1;
 +
ROWID                      N NAME
 +
------------------ ---------- ----------------
 +
AAAR4cAAbAAAACGAAA          1 TEST
 +
SQL> select DBMS_ROWID.ROWID_BLOCK_NUMBER('AAAR4cAAbAAAACGAAA') "Block number" from DUAL;
 +
Block number
 +
------------
 +
        134
 +
SQL> select BLOCK_SIZE from V$DATAFILE where FILE#=27;
 +
BLOCK_SIZE
 +
----------
 +
      8192 <= Bytes
 +
</source>
 +
At this point I know the location of my Data which is stored in Block number 134 and BlockSize of each block is 8K.
 +
Once you have the block number you can dump it using alter system dump datafile command.
 +
 +
===== [5단계] Dump the Individual Block =====
 +
<source lang=sql>
 +
SQL> alter session set tracefile_identifier ='Block_dump';
 +
Session altered.
 +
SQL> ALTER SYSTEM DUMP DATAFILE 27 BLOCK 134;
 +
System altered.
 +
</source>
 +
You can inspect the trace file created for block dump to find the data stored in plain text format
 +
<source lang=bash>
 +
$cat TESTA_ora_16058_Block_dump.trc |grep TEST
 +
</source>
 +
Note:- You can dump individual block or multiple block at a time.
 +
to dump multiple block at once use command below
 +
<source lang=sql>
 +
ALTER SYSTEM DUMP DATAFILE absolute_file_number  BLOCK MIN minimum_block_number BLOCK MAX maximum_block_number;
 +
 +
absolute_file_number <= DataFile Number
 +
minimum_block_number  <= Starting block Number
 +
maximum_block_number;<= Ending Block number
 +
</source>
 +
 +
==== Reading Data Stored in Database Using strings Command ====
 +
Since my datafile is located in a filesystem mount point, if I know the disk and got the root access I can even read the data using strings command on this disk
 +
Let us see how
 +
<source lang=sql>
 +
$df |grep /u01/dbatest1
 +
</source>
 +
 +
==== Login as root user to read the data from /dev/xvde disk ====
 +
<source lang=bash>
 +
#strings /dev/xvde |grep TEST
 +
</source>
 +
 +
==== Reading and Dumping Data Stored in Database Using dd Command ====
 +
dd is another very interesting utility which we can use to read or dump the data directly from the disk.
 +
If I know my datafile name (see step2) together with Block Number and Block Size (see Step 4) where my data is stored I can directly read this blog from disk itself using dd utility even if the database is down. Let us see how
 +
<source lang=bash>
 +
$dd if=/u01/dbatest1/stage/database/db01.dbf bs=8192 skip=142 count=1|strings
 +
</source>
 +
Where
 +
bs<= Database Block Size
 +
Skip<= BlockNumber+Header Blocks(ie 134+8)
 +
Count<= Number of Block to be red or dumped
 +
 +
==== How to Dump the Header Block ====
 +
Procedure of dumping the header block is same as dumping the normal block. Find the header block
 +
using below query
 +
<source lang=sql>
 +
select header_file, header_block from dba_segments where segment_name = ='TABLE_NAME';
 +
</source>
 +
<source lang=sql>
 +
SQL>  select header_file, header_block from dba_segments where segment_name = 'TEST';
 +
HEADER_FILE HEADER_BLOCK
 +
----------- ------------
 +
        27          130
 +
</source>

2024년 5월 23일 (목) 15:01 기준 최신판

thumb_up 추천메뉴 바로가기


1 Block Dump[편집]

  1. 트랜잭션 발생시 어떤 단계에서 어떤 데이터들이 어떤 형태로 변경되는지 이해 필요
  2. 데이터 블록과 언두 영역에서의 데이터 변경에 대한 이해가 반드시 필요
  3. 덤프(Dump) 기능을 이용하면, 트랜잭션에 의해 변경되는 데이터 정보를 물리적으로 관찰 할수 있음

1.1 덤프 방법[편집]

[1단계] 테스트 테이블 생성 후 데이터 1건 입력

CREATE TABLE TB_TEST 
   (	A NUMBER, 
	B VARCHAR2(10)
   )
;

-- 데이터 1건 입력
INSERT INTO TB_TEST VALUES (1,'11');
commit;


[2단계] TB_TEST 테이블의 특정 로우를 다음과 같이 변경

-- 데이터 변경 (A컬럼 값 1를 2로 변경 )
SQL> update TB_TEST set A = 2 where rownum = 1;


[3단계] Update가 이루어진 로우의 위치를 DBMS_ROWID 패키지를 이용하여 찾을수 있다.

SQL>select rowid
         , dbms_rowid.rowid_relative_fno(rowid) as file_no
         , dbms_rowid.rowid_block_number(rowid) as block_no
from TB_TEST where rownum = 1;
ROWID              FILE_NO    BLOCK_NO
------------------ ---------- ----------
AAASk/AAHAAAALcAAA	7	732
  • 변경된 로우가 위치한 블록 주소는 데이터 파일번호가 7번, 블록번호가 732번임을 확인.

[4단계] 이제 이 값을 이용해 해당 데이터 블록을 덤프 할 수 있다.

-- 트레이스 파일 식별자 설정 (트레이스파일을 쉽게 찾기 위해서 설정 )
alter session set tracefile_identifier ='DBCAFE_Block_dump';
SQL> alter system dump datafile 7 block 732

- trace 파일 위치로 이동

-- sqlplus 에서 쉘상태로 나오기 
SQL>! 

-- 트레이스 폴더로 이동 
cd $ORACE_BASE/diag/rdbms/{mongo/MONGO}/trace -- DB마다 {---} 위치가 다름 

-- 트레이스 파일 찾기 
ls |grep DBCAFE_Block_dump;

MONGO_ora_43565_DBCAFE_Block_dump.trc <== 트레이스 파일
MONGO_ora_43565_DBCAFE_Block_dump.trm

-- 트레이스 파일 열기 
vi MONGO_ora_43565_DBCAFE_Block_dump.trc
Trace file /u01/app/oracle/diag/rdbms/mongo/MONGO/trace/MONGO_ora_43565_DBCAFE_Block_dump.trc
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
...... 중략 ....

block_row_dump:
tab 0, row 0, @0x1f86
tl: 9 fb: --H-FL-- lb: 0x2  cc: 2
col  0: [ 2]  c1 03
col  1: [ 2]  31 31

..... 중략 ......

block_row_dump:
tab 0, row 0, @0x1f86
tl: 9 fb: --H-FL-- lb: 0x1  cc: 2
col  0: [ 2]  c1 02
col  1: [ 2]  31 31
end_of_block_dump
Block dump from disk:
buffer tsn: 4 rdba: 0x01c002dc (7/732)
scn: 0x5de721 seq: 0x02 flg: 0x06 tail: 0xe7210602
frmt: 0x02 chkval: 0xdfd5 type: 0x06=trans data
..... 생략 ...


  1. ITL (Interested Transaction List)에 로우를 변경한 트랜잭션이 itl=0x01로 등록되어있다.
  2. 현재 상태는 아직 커밋되지 않은 액티브(Active) 상태이며, 따라서 TX 락을 획득하고 있다.
  3. Xid = 0x0016.026.00003222 인데 이 값을 십진수로 변환하면 USN=22, SLOT=38, SQN=12384가 된다.
  4. V$TRANSACTION 뷰에서 현재 세션에 해당하는 정보를 확인해보면 정확히 일치하는 것을 확인할 수 있다.
SQL> select xidusn,xidslot,xidsqn from v$transaction
where addr = (select taddr from v$session where sid = 162);
XIDUSN XIDSLOT XIDSQN
---------- ---------- ----------
22 38 12834 XID = USN + SLOT + SQN



2) ITL 정보에서 Lock = 1 인데, 이것은 Transaction에 의해 변경된 로우수를 의미

또한 아직 커밋이 수행되지 않았으므로 Flag에는 아무런 값도 세팅되어 있지 않다. 같은 이유로 SCN도 아직 할당되지 않았다.
Flag 값이 “C”이거나 “U”인 경우에는 커밋이 이루어졌다는 것을 의미

3) ITL 정보의 UBA(Undo Block Address)정보를 이용해 현재 트랜잭션이 가장 최근에 사용한 언두 블록과 언두레코드의 위치를 파악할 수 있다.

UBA는 [언두 블록 DBA + Seq# + Record#]으로 이루어진다.
롤백을 수행할 경우 이 정보들을 이용한다.

4) block_row_dump 영역에서 첫번째 로우의 lb값은 0x1로 세팅되어 있다.

lb는 Lock Byte의 약자로, 현재 로우에 대해 락을 건 ITL 번호를 말한다.
1번 ITL이 현재 로우를 변경했음을 의미한다.
Lock byte의 값은 실제로 커밋이 발생해도 정리(Cleanout)되지 않으며, 나중에 Delayed block cleanout 이 발생하거나 다른 프로세스에 의해 블록이 변경되는 경우에 정리된다.
한가지 주의할 것은 첫번째 로우를 변경한 1번 트랜잭션(ITL에 등록된)에서 커밋이 이루어졌는지 아닌지의 여부는 실제로는 언두 세그먼트 헤더의 트랜잭션 테이블을 조회해보아야 알 수 있다는 것이다.
오라클은 커밋이 이루어졌을 때, 트랜잭션에 의해 변경된 모든 데이터 블록의 ITL 에 대해 일일이 커밋 처리를 하지 않는다.
변경된 블록 중 현재 버퍼 캐시에 올라와 있는 것들 중 일부만을 커밋 처리하며, 나머지 블록들에 대해서는 트랜잭션에 할당된 언두 세그먼트 헤더의 트랜잭션 테이블 슬롯에만 커밋 처리를 한다.
이 데이터 블록들은 나중에 다른 세션에 의해 스캔될 때, 실제 Cleanout 처리된다.
이러한 메커니즘을 delayed block cleanout 이라고 부른다.
따라서 현재 특정 로우가 다른 트랜잭션에 의해 변경 중인지의 여부를 완벽하게 파악하려면 ITL 정보뿐만 아니라 때로는 언두 정보까지 같이 조회해야 한다.
한때, 오라클의 최대 장점 중 하나로 로우 레벨 락(Row level lock)을 꼽았던 적이 있다.
오라클의 로우 레벨 락은 명시적으로 존재하는 락이 아니라 위의 정보들이 조합되어 구현되는 논리적인 락이다.
오라클은 개개의 로우를 누가 변경중인지에 대한 목록이나 메타정보를 별도로 관리하지 않는다.
로우가 변경되었는가의 정보는 해당 로우를 직접 방문해보아야만 알 수 있다.
로우 레벨 락이 물리적으로 존재하지 않는다는 것을 이해해야 한다.
로우 레벨 락은 해당 [로우의 변경여부 + 로우를 변경한 트랜잭션정보(ITL) + 언두영역의 트랜잭션 테이블 슬롯 + TX 락]의 정보들이 조합된 일종의 논리적인 락이다.
로우 레벨 락은 상당히 명확하면서도 혼란스러운 개념인데, 이는 대부분의 문서에서 TX 락을 로우 레벨 락이라고 표현하고 있기 때문이다.
심지어 오라클 매뉴얼에서도 애매모호한 표현으로 설명되어 있다.
로우 레벨 락은 TX 락을 이용해 구현되지만 TX 락 자체가 로우 레벨 락은 아니며, 다양한 정보들이 조합되어 로우 레벨 락이 구현된다.

1.2 블럭 덤프 실습[편집]

1.2.1 Dumping Oracle Database Blocks[편집]

As we already know the data in oracle database resides in Tablespace (Logical Container) and each Tablespace has one or more datafile (Physical storage) so lets start with this

1.2.1.1 [1 단계] Create a tablespace[편집]
SQL> create tablespace TS_DBCAFE_01 
              datafile '/u01/dbatest1/stage/database/db01.dbf' size 100M;

Tablespace created.
1.2.1.2 [2단계] Find the Detail of your Tablespace and Datafile[편집]
SQL> select f.FILE#
          , f.NAME "File"
          , t.NAME "Tablespace" 
       from V$DATAFILE f
          , V$TABLESPACE t 
      where t.NAME='TS_DBCAFE_01' 
        and f.TS# = t.TS#;

     FILE# File                                                         Tablespace
---------- ------------------------------------------------------------ ---------------
        27 /u01/dbatest1/stage/database/db01.dbf                        TEST_AU_OS
1.2.1.3 [3 단계] Table 생성 후 테스트 데이터 입력[편집]
SQL> create table test (n number, name varchar2(16)) 
 tablespace TS_DBCAFE_01;
Table created.
SQL> insert into test values (1,'TEST');
1 row created.
SQL> commit;
Commit complete.

At this point we know that my data is stored in a table called "TEST" which is stored in a Tablespace called "TEST_AU_OS" and data physically in a datafile /u01/dbatest1/stage/database/db01.dbf which belongs to "TEST_AU_OS" tablespace Datafile is constructed with database blocks or in other words the space to a datafile is allocated in terms of data blocks( standard DB Block Size is 8K). So let us find out the DB Block Size and Actual Block number which hold my piece of data

1.2.1.4 [4단계] DB Block Size 조회 및 Block Number 조회[편집]
SQL> select ROWID,n,name from test where n=1;
ROWID                       N NAME
------------------ ---------- ----------------
AAAR4cAAbAAAACGAAA          1 TEST
SQL> select DBMS_ROWID.ROWID_BLOCK_NUMBER('AAAR4cAAbAAAACGAAA') "Block number" from DUAL;
Block number
------------
         134
SQL> select BLOCK_SIZE from V$DATAFILE where FILE#=27;
BLOCK_SIZE
----------
      8192 <= Bytes

At this point I know the location of my Data which is stored in Block number 134 and BlockSize of each block is 8K. Once you have the block number you can dump it using alter system dump datafile command.

1.2.1.5 [5단계] Dump the Individual Block[편집]
SQL> alter session set tracefile_identifier ='Block_dump';
Session altered.
SQL> ALTER SYSTEM DUMP DATAFILE 27 BLOCK 134;
System altered.

You can inspect the trace file created for block dump to find the data stored in plain text format

$cat TESTA_ora_16058_Block_dump.trc |grep TEST

Note:- You can dump individual block or multiple block at a time. to dump multiple block at once use command below

ALTER SYSTEM DUMP DATAFILE absolute_file_number  BLOCK MIN minimum_block_number BLOCK MAX maximum_block_number;

absolute_file_number <= DataFile Number
minimum_block_number  <= Starting block Number 
maximum_block_number;<= Ending Block number

1.2.2 Reading Data Stored in Database Using strings Command[편집]

Since my datafile is located in a filesystem mount point, if I know the disk and got the root access I can even read the data using strings command on this disk Let us see how

$df |grep /u01/dbatest1

1.2.3 Login as root user to read the data from /dev/xvde disk[편집]

#strings /dev/xvde |grep TEST

1.2.4 Reading and Dumping Data Stored in Database Using dd Command[편집]

dd is another very interesting utility which we can use to read or dump the data directly from the disk. If I know my datafile name (see step2) together with Block Number and Block Size (see Step 4) where my data is stored I can directly read this blog from disk itself using dd utility even if the database is down. Let us see how

$dd if=/u01/dbatest1/stage/database/db01.dbf bs=8192 skip=142 count=1|strings

Where bs<= Database Block Size Skip<= BlockNumber+Header Blocks(ie 134+8) Count<= Number of Block to be red or dumped

1.2.5 How to Dump the Header Block[편집]

Procedure of dumping the header block is same as dumping the normal block. Find the header block using below query

select header_file, header_block from dba_segments where segment_name = ='TABLE_NAME';
SQL>  select header_file, header_block from dba_segments where segment_name = 'TEST';
HEADER_FILE HEADER_BLOCK
----------- ------------
         27          130