DUL工具是Oracle数据库解救数据的最初伎俩,你用到DUL的时候,大部分状况下,数据库曾经不能启动了,甚至有些
数据 文件曾经损坏了。那么DUL又是怎么在这些极其的状况下把数据导出来的呢?上面咱们就来一步步的剖析它的工作原理。
如 果你想本人开发一个相似的工具,这篇文章也会通知你有那些工作要做,该怎么去做。
Oracle数据库实际上是一堆数据的汇合,数据存储在表中,通过一些软件来治理这些数据,其中读取数据只是这些性能
中的一小部分。在这些数据中最重要的就是用户数据,它们通常保留在数据文件中,依照肯定的格局存储。这些数据怎么解
释成咱们看到的样子,这就须要元数据的帮忙了,通常咱们把元数据叫做数据字典。上面咱们先来看看数据字典是什么样子。
数据字典
Oracle的数据字典也是由一些表组成的。其中最次要的有obj$,tab$,col$这三张表,obj$表中指定了对象的名称,对
象ID,对象的数据ID等,当然也指定了对象的属主ID。tab$表指定了表的一些属性,最次要的是它指定了表开始的地位,在
哪个数据文件中,从哪个块开始。col$表指定了表的列属性,包含列的名称,列ID,列在段中的ID,列的类型,长度等等,
有了col$中的信息,Oracle就能解释存储在数据块中的表的格局了。
表在数据文件中的地位
下面咱们说过,tab$表中有两个字段指定了表开始的地位,一个叫FILE#,批示表在哪个数据文件中,另一个叫BLOCK#,
批示表从哪个块开始。这个开始的块叫段头块,外面蕴含了一个个extent地址范畴,叫做extent map,extent是由间断的数
据块形成的。有了这个extent map,就能够从这些块中读取数据了,这些块就是表的数据块。如果一个表十分大,段头块并
不能蕴含所有的extent,那怎么办呢?Oracle会在这个块中指定下一个extent map的块地址,直到所有的extent map都列
举结束。
有了下面的常识,咱们就能够从数据文件中读取表的数据了。在开始之前,如同还有一点问题,怎么从数据文件中读取
数据字典表呢?数据字典也是表,表的段头地位又是从tab$中失去的,这时咱们还没有读到tab$的数据,如同陷入死循环了。
别急,Oracle在启动的时候会遇到跟咱们一样的问题,它怎么来解决呢?原来Oracle启动时,先在内存中创立一个叫做
bootstrap$的表,这个表中存储了一些建表语句,其中就包含了下面提到的obj$,tab$和col$,乏味的是,在每个建表语句
的前面,还批示了这个表的段头块地位,那么这下就不便了,间接到这个地位找到extent map,遍历所有的extent map找到
属于这个表的数据块,解析数据块中的内容,就能够失去数据字典的信息了。
看到这里,你还有点困惑,那么阐明你思考的深刻,是的,bootstrap$表的开始地位在哪里呢?它保留在1号数据文件的
1号块中,这个块蕴含文件头信息,外面有个叫root dba的字段,蕴含的地址就是bootstrap$表的段头块地址。
数据块
数据块中蕴含了表中的数据,它也是有肯定构造的,开始是块头信息,事务信息,上面是ITL,ITL大小是固定的,叫做事
务槽,块中蕴含几个事务槽,在事务信息中指定。再前面就是数据头信息,紧接着是表目录(table directory)信息,前面是
行目录(row directory),行目录指定了每行数据的地位。再前面就是行数据了,行数据是从块的底部往上来存储的,所以
在行目录和真正的数据之间可能会有一部分闲暇的空间。数据块的构造比较复杂,好在Oracle有一个工具叫做bbed,能够打
开一个数据块,它具体定义了这些数据结构,蕴含数据结构的各个字段,能够不便的看到数据存储的细节。
LONG数据类型
LONG类型的数据个别比拟长,很容易造成行连贯,当然如果一个表创立时字段过多,也会造成行连贯,就是说一行数据
散布在了两个或多个数据块之间,这时怎么办呢?Oracle在每行数据开始都有一个叫做fb的字段,批示数据是否连贯到了下一
个块,如果到了下一个块,那么就会呈现一个网站监控叫做nrid的字段,用来批示前面的数据连贯到了哪里,这是一个地址,代表了在
哪一个块的哪个偏移量。如果下一个块还没有齐全包容这一行数据,那么会有下一个nrid,始终连贯上来,直到数据行完结。
LOB数据类型
LOB是大对象数据类型,是为了代替LONG类型引入的,当数据量比拟小时,它存储在表的块内,如果数据比拟大,就存
储在表外的一个段中,这个段叫做LOB段。LOB数据在LOB段中的地位,由一个叫做定位器的字段来指定,英文名称叫做Lob
Locator,这个定位器存储在表的数据块中,这样读到LOB字段时,就能够通过定位器找到LOB数据。
LOB Index
其实,LOB的存储是相当简单的,默认的状况下,为了不便存储,LOB列在表的数据块中,不仅存储了定位器,还存储了
一些LOB数据块的地址,通过这些地址把LOB数据读出来。然而这些存储的地址个数是有限度的,这取决于表数据块中LOB信
息的长度,默认状况下最多是12个,如果超出了,就要用到定位器了,定位器不能间接找到LOB段的块地位,实际上他是LOB
index的一个键值,通过这个键,在LOB索引中找到一系列的LOB块的地址,通过这些地址把LOB数据读出来。
SecureFile LOB
下面谈到的LOB存储格局叫做BasicFile LOB,从11g开始,Oracle引入了一种新的LOB存储格局,叫做SecureFile LOB。
它简直把LOB index勾销了,而是把LOB的块地址间接放在了LOB段的头块中,通过头块中的地址能够间接读取LOB数据。当
然如果LOB数据量很大很大,头块也放不下这么多地址,那怎么办呢?Oracle在头块中设置了四个地址,别离叫做dba0,
dba1,dba2,dba3。这是一个四级的外部树结构,dba0相当于一个叶子节点,治理了很多LOB数据块地址,当dba0满了,
就会呈现dba1,是dba0的下级节点,它又治理了很多相似dba0的叶子,每个叶子节点块都蕴含了很多LOB数据块的地址,
dba1满了,就会呈现dba2节点,类推下来,到了dba3时,能治理的数据量曾经远超过了LOB数据量的最大限度,这样所有
的LOB数据都能通过这个构造遍历读取了。
Recyclebin
如果你删除了表,从11g开始默认状况下并没有真正删除,而是把表名扭转了,原来的表名存储在了一个叫回收站的表中,
如果你扭转了主见,还能够通过命令复原回来,对误删了表是一个好消息。因为它与一般表没有区别,所以通过下面的常识,
咱们就能复原回来。
Truncate Table
如果一个表被截断了,那可能你就真的拜访不了原来的数据了,如果当初悔恨了,也只能去撞墙了。用咱们后面介绍的
办法能不能找回数据呢?找到表的段头块,dump进去看看,你会发现段头块中的extent map曾经被革除了,这就没法通过
extent map把数据遍历进去了。方法总是有的,数据不是都存储在数据文件中吗?那咱们把所有数据文件中的块都扫描一遍,
把跟这个表的ID统一的那些块都找进去,而后从这些块中把数据都剖析进去,不就能够了吗?只是破费的工夫多一些,并且
要保障不能脱漏了数据文件,实践证明还是能够把数据读出来的。
Drop Table
有了下面截断表的教训,删除的表也就好解决了。段头块的扭转简直与截断表是一样的。与截断表不同的是,你要先把
数据字典中删除的记录复原进去,obj$,tab$,col$表中对于这个表的记录都被删除了,那么怎么复原呢?记得后面咱们提
到过在每行数据后面都有一个叫做fb的字段,其实Oracle并没有把这条数据革除掉,只是在fb字段上做了一个标记,去除这
个标记,这些记录就都复原了。上面再把数据文件扫描一遍,找到属于这个表的块,就能把数据恢复了。
数据字典损坏
最重大的状况就是数据文件中有局部曾经损坏了,那么就不能保障完全恢复数据了。那么首先还是要尝试读取数据字典,
Oracle对根底的数据字典表存储的段头块地位都是固定的,找一个雷同版本的数据库,从bootstrap$表中查找到数据字典的
段头地位,或者从tab$中找到段头地位,而后尝试从这些中央导出数据字典,如果能导出数据字典,剩下的工作就跟后面一
样了。
最坏的状况就是零碎表空间的数据文件失落或者重大损坏,曾经无奈导出数据字典了,那么这时怎么办呢?那么只有通过
数据来重建数据字典了,还是把所有数据文件扫描一遍,记录段头块的地位,每个段头块会对应一个表或一个分区,这样表的
段头地位就找到了,接下来要做的就是重建col$中的字段,次要是数据类型,长度等。有些数据类型的长度是固定的,比方日
期类型,工夫戳类型,很好猜想。数字类型也有本人的特点比拟好确定,剩下的就是字符类型了,大部分猜想不到的都能够先
当做字符类型解决。而后依据重建的数据字典导出一部分数据,这时就要通过人工比对,把字段类型确定分明,而后就能够导
出数据了。