object_id與data_object_id淺析(二)

realkid4發表於2011-03-26

 

接下來使用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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章