在ORACLE裡用儲存過程定期分割表(轉)
在ORACLE裡用儲存過程定期分割表(轉)[@more@] Oracle資料庫裡存放著各種各樣的資料,其中有一些資料表會隨著時間的推移,越來越大。如交友聊天的日誌、簡訊收發的日誌、生產系統的日誌、動態網站釋出系統的日誌等等。這樣的資訊又和時間緊密相關,有沒有辦法讓這些日誌表能按時間自動分割成歷史年月(如log200308,log200309)的表呢? 請看看我用儲存過程定期分割表的方法吧。一、問題的引出 1.初學資料庫時只知道用delete來刪除表裡的資料。但在Oracle資料庫裡,大量delete記錄後,並不能釋放表所佔用的物理空間,這裡面有一個高水位的概念,所以我們不能用delete來分割表。 2.用重新命名(rename)表的方法 (1) 先建一個和原來日誌表(假如是log)資料結構一模一樣的新表(如log_new),建約束、索引及指定欄位的預設值; (2) 重新命名錶log到log_YYYYMM;要注意的問題是OLTP系統可能會因為DML操作阻礙重新命名執行成功,出現ORA-00054資源正忙的錯誤提示,需要試多次才能成功。 (3) 重新命名錶log_new到log。 這樣應用程式不用修改(受影響的時間僅幾秒鐘),日誌表就被截斷分割了。 上述步驟可以在Oracle裡用儲存過程來實現。二、用儲存過程來分割表 可以看到在重新命名錶的方法中,步驟(2)是個關鍵。下面這個rename_table過程會在有鎖阻礙的情況下用遞迴的方式重試100次。重新命名原始表到目標表的儲存過程rename_table:create or replace procedure rename_table(source_name in varchar2,target_name in varchar2,times in out number)isquery_str varchar2(4000);source_name1 varchar2(64);target_name1 varchar2(64);cursor c1 is select segment_name from user_segments where segment_name=upper(source_name);dummy c1%rowtype; cursor c2 is select segment_name from user_segmentswhere segment_name=upper(target_name);dummy2 c2%rowtype; beginsource_name1:=source_name;target_name1:=target_name;open c1;fetch c1 into dummy;-- if c1%found then-- dbms_output.put_line(source_name1||'exist!');-- end if;open c2;fetch c2 into dummy2;-- if c2%notfound then-- dbms_output.put_line(target_name1||'not exist!');-- end if;if c2%notfound and c1%found thenquery_str :='alter table '||source_name1||' rename to '||target_name1;execute immediate query_str;dbms_output.put_line('rename success!');end if;close c1;close c2;exceptionWHEN OTHERS THEN times:=times+1;if times<100 then-- dbms_output.put_line('times:'||times);rename_table(source_name1,target_name1,times);elsedbms_output.put_line(SQLERRM);dbms_output.put_line('error over 100 times,exit');end if;end;/截斷分割log表的儲存過程log_history:create or replace procedure log_historyisquery_str varchar2(32767);year_month varchar2(8);times number;beginselect to_char(sysdate-15,'YYYYMMDD') into year_month from dual;times:=0;query_str :='create table log_new pctfree 10 pctused 80as select * from log where 1=2';execute immediate query_str;query_str :='alter table log_new add constraints log_'||year_month||'_pkprimary key (id) tablespace indx nologging pctfree 10';execute immediate query_str; query_str :='alter table log_his modify logtime default sysdate';execute immediate query_str; query_str :='create index log_'||year_month||'_logtime on log(logtime)tablespace indx nologging pctfree 10';execute immediate query_str; rename_table('log','log'||year_month,times);query_str :='alter table log_new rename to log';execute immediate query_str;end;/ 當然您工作環境的日誌表可能和我這個做例子的日誌表結構上有所不同,約束條件、索引和預設值都不盡相同。只要稍加修改就可以了。三、使用者需要有create any table系統許可權(不是角色裡包含的許可權) 因為在執行儲存過程時,由角色賦予的許可權會失效, 所以執行log_history的使用者一定要有DBA單獨賦予的create any table系統許可權。 最後在OS裡定時每月一號凌晨0:00分執行log_history,讓儲存過程定期分割表。 如果要分割的日誌表很多,模仿log_history可以寫很多類似的儲存過程來分割不同專案裡的日誌表。然後讓OS按月,按周或者不定期的執行這些儲存過程, 管理員只要檢視日誌就可以了。四、其它注意事項 如果應用程式有BUG,可能對在用原始日誌表產生長期不能釋放的鎖,執行log_history重新命名會不成功。 這時DBA可以檢視資料字典:select object_id,session_id,locked_mode from v$locked_object;select t2.username,t2.sid,t2.serial#,t2.logon_time from v$locked_object t1,v$session t2 where t1.session_id=t2.sid order by t2.logon_time; 如果有長期出現的一模一樣的列(包括登入時間),可能是沒有釋放的鎖。 我們要在執行分割日誌表的儲存過程前,用下面SQL語句殺掉長期沒有釋放非正常的鎖:alter system kill session 'sid,serial#';五、結束語 用上面介紹的儲存過程定期分割日誌表有很大的靈活性。歷史資料不僅查詢方便,轉移和備份起來也都很容易。Unix和Windows平臺的都可以使用。對伺服器硬碟空間較小的中小型公司意義尤其明顯。來源:賽迪網 作者:餘
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-942762/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle儲存過程Oracle儲存過程
- oracle的儲存過程Oracle儲存過程
- Oracle儲存過程-1Oracle儲存過程
- Oracle儲存過程乾貨(一):儲存過程基礎Oracle儲存過程
- SQL 儲存過程裡呼叫另一個儲存過程SQL儲存過程
- JAVA儲存過程(轉)Java儲存過程
- 原創:oracle 儲存過程Oracle儲存過程
- oracle儲存過程書寫格式Oracle儲存過程
- Sqlsugar呼叫Oracle的儲存過程SqlSugarOracle儲存過程
- LightDB/PostgreSQL 相容Oracle儲存過程SQLOracle儲存過程
- 儲存過程不好在哪裡?儲存過程
- Sql儲存過程分頁--臨時表儲存SQL儲存過程
- oracle儲存過程和觸發器Oracle儲存過程觸發器
- Oracle 儲存過程分頁 + Sqlsugar呼叫Oracle儲存過程SqlSugar
- oracle使用儲存過程將表資料以excel格式匯出Oracle儲存過程Excel
- ibatis呼叫oracle儲存過程(極簡版)BATOracle儲存過程
- mysql 儲存過程 procedure 批次建表MySql儲存過程
- 用flashback恢復儲存過程儲存過程
- 在Entity Framework中使用儲存過程Framework儲存過程
- Springboot呼叫Oracle儲存過程的幾種方式Spring BootOracle儲存過程
- Oracle 編譯儲存過程卡死解決方法Oracle編譯儲存過程
- MySQL 儲存過程進行切換表MySql儲存過程
- 儲存過程與儲存函式儲存過程儲存函式
- SQLSERVER儲存過程SQLServer儲存過程
- 呼叫儲存過程儲存過程
- mysql 儲存過程MySql儲存過程
- unidac儲存過程儲存過程
- firedac儲存過程儲存過程
- zabbix5.0之postgresql表分割槽操作詳情(儲存過程、定時任務)SQL儲存過程
- Oracle儲存過程中定義多個遊標Oracle儲存過程
- Oracle儲存過程中跳出迴圈的寫法Oracle儲存過程
- Oracle儲存過程乾貨(二):PLSQL控制語句Oracle儲存過程SQL
- Oracle儲存過程編譯卡死的解決方法Oracle儲存過程編譯
- oracle儲存過程許可權繼承小結Oracle儲存過程繼承
- PostgreSQL獲取建表語句儲存過程SQL儲存過程
- ORACLE PL/SQL 物件、表資料對比功能儲存過程簡單實現OracleSQL物件儲存過程
- MySQL儲存過程裡動態SQL的使用UXMySql儲存過程UX
- JdbcTemplate調儲存過程JDBC儲存過程
- 造數儲存過程儲存過程