Oracle dbms_redefinition線上重定義表結構
剛接手一套系統應用資料庫,因為專案建設期間種種原因,庫是非歸檔模式也沒有備份,更讓我無語的是有個表增長的比較快,將近90G大小,每隔一段時間都要刪除前三個月以前的資料,然後再用shrink收縮空間,因為是非分割槽表,shrink很是浪費時間,而且很多時間無法正常完成shrink操作,想將它改成分割槽表,同時業務部門又允許停資料庫,只能利用ORACLE 10g的一個新特性,DBMS_REDEFINITION包線上轉換成分割槽表,然後將以前的分割槽直接truncate掉,這樣以前幾個小時才能完成的工作,1分鐘內就可以搞定,具體操作過程如下。
操作環境說明:
ORACLE 10G 10.2.0.4,
HP-UNIX系統
DBMS_REDEFINITION包支援線上對錶結構進行重定義,包括新增、刪除列等操作,整個操作過程中只在資料同步時對原表臨時進行加鎖處理,基本上可以忽略對業務的影響,特別是對於銀行、電信行業非RAC環境使用DBMS_REDEFINITION對錶行DDL修改是一種非常不錯的選擇。
在這裡我們只用DBMS_REDEFINITION對非區表完成分割槽轉換,具體使用方法如下:
第一步:選擇轉換方法
有兩種選擇,一種是建立主鍵,我的生產環境沒有主鍵,那麼我們只能選擇rowid這種方法
第二步:檢查表是否可以重定義
begin
DBMS_REDEFINITION.CAN_REDEF_TABLE(uname =>'orabpel',
tname =>'AUDIT_TRAIL',
options_flag => dbms_redefinition.cons_use_rowid
第三步:建立轉換臨時表
說明:因10g不支援間隔分割槽,只能通過手工進行建立分割槽,圖片只顯示了部分內容,下面基本上一樣,需要注意日期的寫法,同時要注意分割槽只能將小的日期放在前面,大的放在後面,否則會報ORA-14037分割槽"AUDIT_TRAIL"分割槽界限過高!
第四步:設定並行操作
alter session force parallel dml parallel 4;
alter session force parallel query parallel 4;
第五步:開始重定義表結構
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE(uname => 'orabpel',
orig_table => 'AUDIT_TRAIL',
int_table => 'AUDIT_TRAIL_EMP',
options_flag => dbms_redefinition.cons_use_rowid
); --紅色部分容易忽略
END;
注意:此過程比較消耗時間,會把中間表填滿資料,所以此時要有足夠的空間產生新中間表資料
第六步:同步臨時表
BEGIN
DBMS_REDEFINITION.SYNC_INTERIM_TABLE(uname => 'orabpel',
orig_table => 'AUDIT_TRAIL',
int_table => 'AUDIT_TRAIL_EMP'
);
END;
--此過程比較快,只是同步從開始轉換到現在產生的新資料
第七步:完成重定義
BEGIN
DBMS_REDEFINITION.FINISH_REDEF_TABLE(uname => 'orabpel',
orig_table => 'AUDIT_TRAIL',
int_table => 'AUDIT_TRAIL_EMP'
);
END;第八步:刪除臨時表
BEGIN
truncate table AUDIT_TRAIL_EMP;--大表不要忘記這步操作哦
drop table AUDIT_TRAIL_EMP; --刪除臨時表的定義
END;
如果順利的話到此就結束了,原表變成了分割槽表,在沒有停業務的情況下完成了表的線上重定義,但是操作過程中往往沒那麼順利,執行過程中報錯怎麼處理呢?
第九步:異常情況下終止操作
BEGIN
DBMS_REDEFINITION.ABORT_REDEF_TABLE(uname => 'orabpel',
orig_table => 'AUDIT_TRAIL',
int_table => 'AUDIT_TRAIL_EMP'
);
END;
在執行任何一步出錯,都可以執行第九步終止轉換操作!
第十步:檢查驗證有效性
做完以後一定要檢查是否有失效對像
select * from dba_objects where status<>'VALID' and owner='orabpel';
發現有失效的包 ,處理方法
alter package orabpel.collxa compile;
處理完失效對像後檢視最後一個分割槽的資料是否在增長,驗證轉換後分區是否可用
select count(*) from orabpel.audit_trail_1309;
發現數據並沒有增長,肯定是那裡出了問題,然後檢視alert.log是否有報錯
發現報錯如下:
Some indexes or index [sub]partitions of table ORABPEL.AUDIT_TRAIL have been marked unusable
處理方法如下:
SELECT 'ALTER INDEX ' || INDEX_OWNER || '.' || INDEX_NAME ||
'REBUILD PARTITION ' || PARTITION_NAME || ' NOLOGGING online;'
FROM DBA_IND_PARTITIONS
WHERE INDEX_OWNER NOT IN ('SYS', 'SYSTEM', 'PUBLIC')
AND STATUS = 'UNUSABLE'
UNION ALL
SELECT 'alter index ' || OWNER || '.' || A.INDEX_NAME ||
' REBUILD online nologging;'
FROM DBA_INDEXES A
WHERE OWNER NOT IN ('SYS', 'SYSTEM', 'PUBLIC')
AND STATUS = 'UNUSABLE';
跟據執行結果執行,否則資料將不能正常寫入,(切記!)
alter index ORABPEL.CS_PK1 REBUILD online nologging;
再次查詢分割槽表資料是否正常寫入
select count(*) from orabpel.audit_trail;
發現數據增長很快,至此操作驗證成功!
總結:線上重定義並不能100%保證不影響業務,我在測試庫上發現不影響業務,但是在正式庫操作完以報最新分割槽表資料並沒有增加,alert.log報上面的錯誤,處理完以後資料才正常寫入,因此操作完以後一定要記得檢視dba_objects去及時處理失效對像,同時檢視alert.log是否有異常資訊及時進行相應的處理,最後一定要驗證最後一個分割槽表資料是否在增長,只能這樣我們才能確認我們轉換後的分割槽表是可用的!特別需要注意的是,如果你的庫是10g的庫,一定要及時增加分割槽,因為10g不支援間隔分割槽,需要人為手工的及時新增新的分割槽,如果在11g裡面間隔分割槽可以做到自動新增新的分割槽,但是看錶的DDL語句時發現並沒有隔間分割槽的關鍵字,這就是為什麼同樣的語句在10g需要手工新增分割槽,而在11g卻可以自動增加分割槽的原因。不知道為什麼11g中間隔分割槽表DDL語句看不到間隔分割槽關鍵字,知道的朋友可以QQ交流一下!