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&