block中真实存储的数据oracle
  IE5LYMWlmdvL 2023年11月02日 67 0

概念描述

通常数据库的一张表会存储number、char等等类型的数据,这些数据通过select查询就能被人所识别,但是Oracle数据库存储这些数据的时候却不会“明文”存储。如果我们能把表对应的dbf表空间文件下载下来,再通过一些转换手段将dbf中的数据块内容转换成人能识别的“明文”,但首先必须知道它的“转换机制”。

测试验证

首先我们要能定位到我们找的数据所在的物理位置在哪里,然后再查看Oracle存储的真实数据。

  1. 找到一行数据的物理位置

方法1、
如果找到一行数据的物理位置?可以通过rowid来定位。但是rowid又是一串字符,这就需要将它转换一下。(注意 rowid不是真实存在于块中的物理数据,它只是一个“拼接”而成的列)

set linesize 1000 pagesize 1000
col OTHER_COL for a20
select id,name,OTHER_COL,rowid from test;

block中真实存储的数据oracle_rowid

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;

block中真实存储的数据oracle_block_02

至此,定位到这一行数据所在的位置就是第8号文件 第#140号块 第0行。

方法2、

请dump出L1 BMB,自行观察内容。

找到这个表的“段头块”再找到“L2 BMB”再找到“L1 BMB”:

block中真实存储的数据oracle_block_03


如上图,0x0200080转换成8号文件128号块,通过L1 BMB可以看到,插入的那一行数据是在第8号文件的第140号块(128 + 12 = 140)。

  1. 查看块真实数据

现在dump出这个第8号文件 第#140号块的所有内容:

alter system dump datafile 8 block 140;
select * from v$diag_info where name='Default Trace File';

block中真实存储的数据oracle_16进制_04


如上图解释;关于值的大小解释如下:

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;

block中真实存储的数据oracle_block_05

  1. 转换机制
    通过上述的介绍,其实数据的存储是被转换过的。接下来就看看字符和数值是如何转换的。
    3.1、字符转换
    实际上是 string --> ASCII(十进制 )–> 十六进制
    转回来是:十六进制–>ASCII(十进制 )–>string
select ascii('1') ,ascii('_'),ascii('a') from dual;  --将字符装换成10进制

block中真实存储的数据oracle_16进制_06

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;

block中真实存储的数据oracle_块_07


转换回来:

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;

block中真实存储的数据oracle_ancii_08

3.2、数值转换机制

直接可以看到,真实的数据 0 ,1 ,2 存在块中的存储值为 “80” ,“c1,2” ,“c1,3” 。 它们是如何得到的呢?

block中真实存储的数据oracle_block_09

正数举例1如下:
1 = 1 x power(100,0) 取得最高指数就是0,取得所有基数1 ; 指数0+193=193,基数1+1=2 ,最后逐个转换为16进制:c1,2

block中真实存储的数据oracle_block_10

验证如下:

block中真实存储的数据oracle_ancii_11

正数举例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

block中真实存储的数据oracle_ancii_12

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

IE5LYMWlmdvL