• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    軟件測試中在ORACLE里用存儲過程定期分割表

    發布: 2010-7-02 09:08 | 作者: 網絡轉載 | 來源: 領測軟件測試網采編 | 查看: 17次 | 進入軟件測試論壇討論

    領測軟件測試網

    軟件測試中在ORACLE里用存儲過程定期分割表 

    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)
      is
    query_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_segments
     where segment_name=upper(target_name);
    dummy2 c2%rowtype; 
    begin
    source_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 then
    query_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;
    exception
    WHEN OTHERS THEN  
    times:=times+1;
    if times<100 then
    --  dbms_output.put_line('times:'||times);
    rename_table(source_name1,target_name1,times);
    else
    dbms_output.put_line(SQLERRM);
    dbms_output.put_line('error over 100 times,exit');
    end if;
    end;
    
    /
    截斷分割log表的存儲過程log_history:
    create or replace procedure log_history
    is
    query_str varchar2(32767);
    year_month 	varchar2(8);
    times	number;
    begin
    select to_char(sysdate-15,'YYYYMMDD') into year_month from dual;
    times:=0;
    query_str :='create table log_new pctfree 10 pctused 80
    as select * from log where 1=2';
    execute immediate query_str;
    query_str :='alter table log_new add constraints log_'
     ||year_month||'_pk
    primary 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#';
    


    五、結束語

      用上面介紹的存儲過程定期分割日志表有很大的靈活性。歷史數據不僅查詢方便,轉移和備份起來也都很容易。UnixWindows平臺的都可以使用。對服務器硬盤空間較小的中小型公司意義尤其明顯。

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/

    TAG: oracle Oracle ORACLE 軟件測試 定期


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備2023014753號-2
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>