oracle判断数据出现交叉,Oracle move table分析
在move操作的時候,進(jìn)行的是block之間的數(shù)據(jù)copy,所以table所位于的block的區(qū)域會發(fā)生變化;所有行物理存儲的順序不會發(fā)生變化,但行號會變成按AAA增1的順子,所以block里行會挪緊,實現(xiàn)了消除HWM和行碎片(包括行遷移問題),但不會釋放申請的空間(其他segment不能使用此部分的空閑空間,只能本segment增加數(shù)據(jù)時使用),得到了空閑空間但不釋放,更說明是block之間的copy,只是block內(nèi)行會挪緊。當(dāng)前的tablespace中需要有1倍于table的空閑空間以供使用。所有行的rowid都發(fā)生了變化,index是通過rowid來fetch數(shù)據(jù)行的,所以,table上的index是必須要rebuild的。table在進(jìn)行move操作時,table上加了exclusive?lock,我們只能對它進(jìn)行select的操作。反過來說,當(dāng)我們的一個session對table進(jìn)行DML操作且沒有commit時,在另一個session中是不能對這個table進(jìn)行move操作的,否則oracle會返回這樣的錯誤信息:ORA-00054:?資源正忙,要求指定?NOWAIT。最后重新編譯數(shù)據(jù)庫所有失效的對象,收集新的table統(tǒng)計分析數(shù)據(jù)。
實驗:
1.建表并插入數(shù)據(jù):
SQL>?create?table?sjh.test1(id?int)?tablespace?users;
表已創(chuàng)建。
SQL>?insert?into?sjh.test1?values(1);
已創(chuàng)建?1?行。
SQL>?insert?into?sjh.test1?values(2);
已創(chuàng)建?1?行。
SQL>?insert?into?sjh.test1?values(3);
已創(chuàng)建?1?行。
SQL>?insert?into?sjh.test1?values(4);
已創(chuàng)建?1?行。
SQL>?insert?into?sjh.test1?values(5);
已創(chuàng)建?1?行。
SQL>?insert?into?sjh.test1?values(6);
已創(chuàng)建?1?行。
SQL>?insert?into?sjh.test1?values(7);
已創(chuàng)建?1?行。
SQL>?insert?into?sjh.test1?values(8);
已創(chuàng)建?1?行。
SQL>?commit;
提交完成。
SQL>?select?*?from?sjh.test1;
ID
----------
1
2
3
4
5
6
7
8
已選擇8行。
2.查看表的rowid信息和block?id信息:
SQL>?select?rowid,id?from?sjh.test1;
ROWID??????????????????????ID
------------------?----------
AAAMlQAAEAAAABHAAA??????????1
AAAMlQAAEAAAABHAAB??????????2
AAAMlQAAEAAAABHAAC??????????3
AAAMlQAAEAAAABHAAD??????????4
AAAMlQAAEAAAABHAAE??????????5
AAAMlQAAEAAAABHAAF??????????6
AAAMlQAAEAAAABHAAG??????????7
AAAMlQAAEAAAABHAAH??????????8
已選擇8行。
SQL>?select?EXTENT_ID,FILE_ID,RELATIVE_FNO,BLOCK_ID,BLOCKS
2???from?dba_extents?where?segment_name='TEST1';
EXTENT_ID????FILE_ID?RELATIVE_FNO???BLOCK_ID?????BLOCKS
----------?----------?------------?----------?----------
0??????????4????????????4?????????65??????????8
--8條記錄都在一個塊上(AAAABH)
這里簡單介紹一下ROWID的知識:ROWID?在磁盤上需要10個字節(jié)的存儲空間并使用18個字符來顯示它包含下列組件:
數(shù)據(jù)對象編號:每個數(shù)據(jù)對象如表或索引在創(chuàng)建時都分配有此編號,并且此編號在數(shù)據(jù)庫中是唯一的;
相關(guān)文件編號:此編號對于一個表空間中的每個文件是唯一的;
塊編號:表示包含此行的塊在文件中的位置;
行編號:標(biāo)識塊頭中行目錄位置的位置;
在內(nèi)部數(shù)據(jù)對象編號需要32?位,相關(guān)文件編號需要10?位,塊編號需要22,位行編號需要16?位,加起來總共是80?位或10?個字節(jié),ROWID?使用以64?為基數(shù)的編碼方案來顯示該方案將六個位置用于數(shù)據(jù)對象,編號三個位置用于相關(guān)文件編號六個位置用于塊編號三個位置用于行編號以64?為基數(shù)的編碼方案使用字符A-Z?a-z?0-9?+?和/共64?個字符。
如下例所示:AAAMlQ?AAE?AAAABH?AAA
在本例中
AAAMlQ????是數(shù)據(jù)對象編號
AAE???????是相關(guān)文件編號
AAAABH???是塊編號
AAA??????是行編號
3.做一些DML操作,再觀察ROWID有沒有發(fā)生變化:
SQL>?delete?from?sjh.test1?where?id=1;
已刪除?1?行。
SQL>?delete?from?sjh.test1?where?id=3;
已刪除?1?行。
SQL>?delete?from?sjh.test1?where?id=5;
已刪除?1?行。
SQL>?commit;
提交完成。
SQL>?select?rowid,id?from?sjh.test1;
ROWID??????????????????????ID
------------------?----------
AAAMlQAAEAAAABHAAB??????????2
AAAMlQAAEAAAABHAAD??????????4
AAAMlQAAEAAAABHAAF??????????6
AAAMlQAAEAAAABHAAG??????????7
AAAMlQAAEAAAABHAAH??????????8
--我們看到ROWID保持不變。
4.做MOVE操作,然后觀察ROWID的情況:
SQL>?alter?table?sjh.test1?move;
表已更改。
SQL>?select?rowid,id?from?sjh.test1;
ROWID??????????????????????ID
------------------?----------
AAAMlRAAEAAAABMAAA??????????2
AAAMlRAAEAAAABMAAB??????????4
AAAMlRAAEAAAABMAAC??????????6
AAAMlRAAEAAAABMAAD??????????7
AAAMlRAAEAAAABMAAE??????????8
SQL>?select?EXTENT_ID,FILE_ID,RELATIVE_FNO,BLOCK_ID,BLOCKS
2???from?dba_extents?where?segment_name='TEST1';
EXTENT_ID????FILE_ID?RELATIVE_FNO???BLOCK_ID?????BLOCKS
----------?----------?------------?----------?----------
0??????????4????????????4?????????73??????????8
--ROWID發(fā)生變化BLOCK_ID由原來的65變?yōu)?3,BLOCK的編號由原來的AAAABH變?yōu)锳AAABM
5.move對HWM的影響:
SQL>?create?table?my_objects?tablespace?HWM
2???as?select?*?from?all_objects;
SQL>?delete?from?my_objects?where?rownum<10000;
9999?rows?deleted
SQL>?select?count(*)?from?my_objects;
COUNT(*)
----------
21015
SQL>?exec?show_space(p_segname?=>?'MY_OBJECTS',p_owner?=>?'DLINGER',p_type?=>?'TABLE');
Total?Blocks............................425
Total?Bytes.............................3481600
Unused?Blocks...........................3
Unused?Bytes............................24576
Last?Used?Ext?FileId....................11
Last?Used?Ext?BlockId...................1294
Last?Used?Block.........................2
這里HWM=425?-?3?+?1?=?423
然后對table?MY_OBJECTS進(jìn)行move操作:
SQL>?alter?table?MY_OBJECTS?move;
表已更改。
SQL>?exec?show_space(p_segname?=>?'MY_OBJECTS',p_owner?=>?'DLINGER',p_type?=>?'TABLE');
Total?Blocks............................290
Total?Bytes.............................2375680
Unused?Blocks...........................1
Unused?Bytes............................8192
Last?Used?Ext?FileId....................11
Last?Used?Ext?BlockId...................1584
Last?Used?Block.........................4
我們可以看到,table?MY_OBJECTS的HWM從423移動到290,table的HWM降低了!(show_space是自定義的一個過程)。
Move的一些用法:
以下是alter?table?中move子句的完整語法,我們介紹其中的幾點:
MOVE?[ONLINE]
[segment_attributes_clause]
[data_segment_compression]
[index_org_table_clause]
[?{?LOB_storage_clause?|?varray_col_properties?}
[?{?LOB_storage_clause?|?varray_col_properties?}?]...
]
[parallel_clause]
a.?我們可以使用move將一個table從當(dāng)前的tablespace上移動到另一個tablespace上,如:
alter?table?t?move?tablespace?tablespace_name;
b.?我們還可以用move來改變table已有的block的存儲參數(shù),如:
alter?table?t?move?storage?(initial?30k?next?50k);
c.另外,move操作也可以用來解決table中的行遷移的問題。
使用move的一些注意事項:
a.?table上的index需要rebuild:
在前面我們討論過,move操作后,數(shù)據(jù)的rowid發(fā)生了改變,我們知道,index是通過rowid來fetch數(shù)據(jù)行的,所以,table上的index是必須要rebuild的。
SQL>?create?index?i_my_objects?on?my_objects?(object_id);
Index?created
SQL>?alter?table?my_objects?move;
Table?altered
SQL>?select?index_name,status?from?user_indexes?where?index_name='I_MY_OBJECTS';
INDEX_NAME?????????????????????STATUS
------------------------------?--------
I_MY_OBJECTS???????????????????UNUSABLE
從這里可以看到,當(dāng)table?MY_OBJECTS進(jìn)行move操作后,該table?上的inedx的狀態(tài)為UNUSABLE,這時,我們可以使用alter?index?I_MY_OBJECTS?rebuild?online的命令,對index?I_MY_OBJECTS進(jìn)行在線rebuild。
b.?move時對table的鎖定
當(dāng)我們對table?MY_OBJECTS進(jìn)行move操作時,查詢v$locked_objects視圖可以發(fā)現(xiàn),table?MY_OBJECTS上加了exclusive?lock:
SQL>select?OBJECT_ID,?SESSION_ID,ORACLE_USERNAME,LOCKED_MODE?from?v$locked_objects;
OBJECT_ID?SESSION_ID?ORACLE_USERNAME????LOCKED_MODE
----------?----------?------------------?-----------
32471??????????9?DLINGER??????????????????????6
SQL>?select?object_id?from?user_objects?where?object_name?=?'MY_OBJECTS';
OBJECT_ID
----------
32471
這就意味著,table在進(jìn)行move操作時,我們只能對它進(jìn)行select的操作。反過來說,當(dāng)我們的一個session對table進(jìn)行DML操作且沒有commit時,在另一個session中是不能對這個table進(jìn)行move操作的,否則oracle會返回這樣的錯誤信息:ORA-00054:?資源正忙,要求指定?NOWAIT。
c.?關(guān)于move時空間使用的問題:
當(dāng)我們使用alter?table?move來降低table的HWM時,有一點是需要注意的,這時,當(dāng)前的tablespace中需要有1倍于table的空閑空間以供使用:
SQL>?CREATE?TABLESPACE?TEST1
2???DATAFILE?'D:\ORACLE\ORADATA\ORACLE9I\TEST1.dbf'?SIZE?5M
3???UNIFORM?SIZE?128K?;
SQL>?create?table?my_objects?tablespace?test1?as?select?*?from?all_objects;
表已創(chuàng)建。
SQL>?select?bytes/1024/1024?from?user_segments?where?segment_name='MY_OBJECTS';
BYTES/1024/1024
---------------
3.125
SQL>?alter?table?MY_OBJECTS?move;
alter?table?MY_OBJECTS?move
*
ERROR?位于第?1?行:
ORA-01652:?無法通過16(在表空間TEST1中)擴(kuò)展?temp?段
SQL>?ALTER?DATABASE
2??DATAFILE?'D:\ORACLE\ORADATA\ORACLE9I\TEST1.DBF'?RESIZE?7M;
數(shù)據(jù)庫已更改。
SQL>?alter?table?MY_OBJECTS?move;
表已更改。
總結(jié)
以上是生活随笔為你收集整理的oracle判断数据出现交叉,Oracle move table分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 外部中断实验 编写程序学习外部中断的电平
- 下一篇: 升级计算机方案,关于计算机升级方案