接下来使用truncate命令
SQL> alter session set events '10046 trace name context forever, level 4';
Session altered
SQL> truncate table t;
Table truncated
SQL> select f_get_trace_name from dual;
F_GET_TRACE_NAME
--------------------------------
D:\ORACLE\PRODUCT\10.2.0\ADMIN\ORCL\UDUMP\orcl_ora_2052.trc
观察数据表段情况。
SQL> select object_id,data_object_id from user_objects where object_name='T';
OBJECT_ID DATA_OBJECT_ID
---------- --------------
54038 54044
SQL> select segment_name, header_file, header_block from dba_segments where segment_name='T' and wner='SCOTT';
SEGMENT_NAME HEADER_FILE HEADER_BLOCK
-------------------- ----------- ------------
T 4 4203
注意:此处发生了变化。object_id没有变化,而data_object_id引入了一个新值。但是,进行truncate操作的时候,文件和文件头块的信息没有发生变化。
此时,我们检查跟踪文件,发现存在对数据字典表obj$,seg$等的更新内容。新的data_object_id想必也就是在此时被写入。
update obj$ set obj#=:6,type#=:7,ctime=:8,mtime=:9,stime=:10,status=:11,dataobj#=:13,flags=:14,oid$=:15,spare1=:16, spare2=:17 where owner#=:1 and name=:2 and namespace=:3 and(remoteowner=:4 or remoteowner is null and :4 is null)and(linkname=:5 or linkname is null and :5 is null)and(subname=:12 or subname is null and :12 is null)
END OF STMT
PARSE #6:c=0,e=46,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=11607801963
BINDS #6:
kkscoacd
Bind#0
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=07eaf764 bln=24 avl=04 flg=05
value=54038
(篇幅原因,有省略…)
Bind#6
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0
kxsbbbfp=07eaf6f8 bln=24 avl=04 flg=05
value=54044
(篇幅原因,有省略…)
=====================
查找对应的seg$数据字典表,对应的段头信息是存在的。相当于对应的原始段信息存在。
SQL> select * from seg$ where file#=4 and block#=4203;
FILE# BLOCK# TYPE# TS# BLOCKS EXTENTS INIEXTS MINEXTS MAXEXTS EXTSIZE EXTPCT USER# LISTS GROUPS BITMAPRANGES CACHEHINT SCANHINT HWMINCR SPARE1 SPARE2
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ ---------- ---------- ---------- ---------- ----------
4 4203 5 4 8 1 8 1 2147483645 128 0 54 0 0 0 0 0 54044 131329
注意,虽然文件和头块的位置没有发生变化,但是每行数据中对对象编号data_object_id的变化是落实的。
SQL> insert into t select * from dba_objects;
50358 rows inserted
SQL> commit;
Commit complete
SQL> select dbms_rowid.rowid_object(t.rowid) from t where rownum<5;
DBMS_ROWID.ROWID_OBJECT(T.ROWI
------------------------------
54044
54044
54044
54044
//此时,rowid对应的是物理data_object_id
结论:我们可以得到这样的结论。
首先,data_object_id是类似于段对象编号的作用。当一个段出现的时候,系统按照分配原则进行分配。如果段结构因为某种原因删除破坏,这个编号就消失,好像从未出现过一样。
其次,object_id是逻辑层面上的编号,针对一个逻辑对象。稳定性相对于物理段要稳定得多。
最后,truncate本质上是一种ddl语句。方式是基于对数据表segment结构的重构,实验中我们可以清晰看到原有segment对象的破坏和重构。但是,从我们的案例上看,新segment结构是可能会重用旧segment的空间和位置信息的,但是对Oracle和我们来说,他已经是一个新的segment对象了。
那么,有没有可能出现新segment的构建,并且物理位置变化呢?答案是肯定的。我们进行move操作,就可以实现这个目标。简单的下面实验。
SQL> select segment_name, header_file, header_block from dba_segments where segment_name='T' and wner='SCOTT';
SEGMENT_NAME HEADER_FILE HEADER_BLOCK
-------------------- ----------- ------------
T 4 4203
SQL> delete t where wner='PUBLIC';
19989 rows deleted
SQL> commit;
Commit complete
SQL> alter table t move;
Table altered
SQL> select segment_name, header_file, header_block from dba_segments where segment_name='T' and wner='SCOTT';
SEGMENT_NAME HEADER_FILE HEADER_BLOCK
-------------------- ----------- ------------
T 4 6651
SQL> select object_id,data_object_id from user_objects where object_name='T';
OBJECT_ID DATA_OBJECT_ID
---------- --------------
54038 54045
Move操作是从物理上直接对对象进行操作整理。经过对数据表的move操作,我们实现了我们的猜想。进行move操作时,数据行要进行重新的rowid排列,其中就包括新的segment对象设置。从原来的头块4203,转移到了6651。Data_object_id也被分配了一个新的编号54045。
综合来说,对Oracle来说,逻辑object_id是稳定的,而对应的物理位置和段对象是多变的。这点在我们进行字典分析的时候,需要额外注意。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-690631/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/17203031/viewspace-690631/