概念描述
通常数据库的一张表会存储number、char等等类型的数据,这些数据通过select查询就能被人所识别,但是Oracle数据库存储这些数据的时候却不会“明文”存储。如果我们能把表对应的dbf表空间文件下载下来,再通过一些转换手段将dbf中的数据块内容转换成人能识别的“明文”,但首先必须知道它的“转换机制”。
测试验证
首先我们要能定位到我们找的数据所在的物理位置在哪里,然后再查看Oracle存储的真实数据。
- 找到一行数据的物理位置
方法1、
如果找到一行数据的物理位置?可以通过rowid来定位。但是rowid又是一串字符,这就需要将它转换一下。(注意 rowid不是真实存在于块中的物理数据,它只是一个“拼接”而成的列)
set linesize 1000 pagesize 1000
col OTHER_COL for a20
select id,name,OTHER_COL,rowid from test;
select id,name,rowid,
dbms_rowid.ROWID_RELATIVE_FNO(rowid) file_no,
dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block_no,
dbms_rowid.ROWID_ROW_NUMBER(rowid) row_no
from test;
至此,定位到这一行数据所在的位置就是第8号文件 第#140号块 第0行。
方法2、
请dump出L1 BMB,自行观察内容。
找到这个表的“段头块”再找到“L2 BMB”再找到“L1 BMB”:
如上图,0x0200080转换成8号文件128号块,通过L1 BMB可以看到,插入的那一行数据是在第8号文件的第140号块(128 + 12 = 140)。
- 查看块真实数据
现在dump出这个第8号文件 第#140号块的所有内容:
alter system dump datafile 8 block 140;
select * from v$diag_info where name='Default Trace File';
如上图解释;关于值的大小解释如下:
col 0: [ 2] c1 02 id(number),值:1
col 1: [ 3] 31 5f 61 name(varchar2)值:1_a
col 2: [2000] 63 72 77 20 other_col(char(2000))值:crw
所以原始SQL:
insert into test values(1,‘1_a’,‘crw’);
实际SQL:
insert into test values(dump(1,16),
dump(‘1_a’,16),
dump(‘crw’,16)
);
select dump(1,16) from dual;
select dump('1_a',16) from dual;
select dump('crw',16) from dual;
- 转换机制
通过上述的介绍,其实数据的存储是被转换过的。接下来就看看字符和数值是如何转换的。
3.1、字符转换
实际上是 string --> ASCII(十进制 )–> 十六进制
转回来是:十六进制–>ASCII(十进制 )–>string
select ascii('1') ,ascii('_'),ascii('a') from dual; --将字符装换成10进制
select to_char(ascii('1'),'xxxxxxxxxxxxx') from dual --再将10进制转换成16进制
union
select to_char(ascii('_'),'xxxxxxxxxxxxx') from dual
union
select to_char(ascii('a'),'xxxxxxxxxxxxx') from dual;
转换回来:
select CHR(to_number('31','xxxxxxxxxxx')) from dual
union
select CHR(to_number('5f','xxxxxxxxxxx')) from dual
union
select CHR(to_number('61','xxxxxxxxxxx')) from dual;
3.2、数值转换机制
直接可以看到,真实的数据 0 ,1 ,2 存在块中的存储值为 “80” ,“c1,2” ,“c1,3” 。 它们是如何得到的呢?
正数举例1如下:
1 = 1 x power(100,0) 取得最高指数就是0,取得所有基数1 ; 指数0+193=193,基数1+1=2 ,最后逐个转换为16进制:c1,2
验证如下:
正数举例2如下:
12345 = 1 x power(100,2) + 23 x power(100,1) + 45* power(100,0) 取得最高指数是2,取得所有基数1,23,45 ;指数2+193=195,基数+1=2,24,46 ;最后逐个转换为16进制:c3,2,18,2e
标签:存储,rowid,dump,16,block,dual,oracle,ascii,select From: https://blog.51cto.com/u_13482808/7474215