国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數(shù)據(jù)庫 > Oracle > 正文

在ORACLE里用存儲過程定期分割表

2024-08-29 13:47:40
字體:
供稿:網(wǎng)友

         Oracle數(shù)據(jù)庫里存放著各種各樣的數(shù)據(jù),其中有一些數(shù)據(jù)表會隨著時間的推移,越來越大。如交友聊天的日志、
    短信收發(fā)的日志、生產(chǎn)系統(tǒng)的日志、動態(tài)網(wǎng)站發(fā)布系統(tǒng)的日志等等。這樣的信息又和時間緊密相關(guān),有沒有辦法
    讓這些日志表能到時間自動分割成歷史年月(如log200308,log200309)的表呢? 請看看我用存儲過程定期分割表的
    方法吧。
   
    一、問題的引出
   
      1.初學(xué)數(shù)據(jù)庫時只知道用delete來刪除表里的數(shù)據(jù)。但在Oracle數(shù)據(jù)庫里,大量delete記錄后,并不能釋放表
        所占用的物理空間,這里面有一個高水位的概念,所以我們不能用delete來分割表。
       
      2.用重命名(rename)表的方法
     
       (1).先建一個和原來日志表(假如是log)數(shù)據(jù)結(jié)構(gòu)一模一樣的新表(如log_new),建約束、索引及指定字段的默
           認(rèn)值;
       (2).重命名表log到log_YYYYMM; 
       要注重的問題是OLTP系統(tǒng)可能會因為DML操作阻礙重命名執(zhí)行成功,出現(xiàn)ORA-00054資源正忙的錯誤提示,
       需要試多次才能成功。
       (3).重命名表log_new到log。
           這樣應(yīng)用程序不用修改(受影響的時間僅幾秒鐘),日志表就被截斷分割了。
          
        上述步驟可以在Oracle里可以用存儲過程來實現(xiàn)它們。
       
    二、用存儲過程來分割表
       
        可以看到在重命名表的方法中,步驟(2)是個要害。
        下面這個rename_table過程會在有鎖阻礙的情況下用遞歸的方式重試100次。  

       重命名原始表到目標(biāo)表的存儲過程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,'YYYYMM') 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;
       /

當(dāng)然您工作環(huán)境的日志表可能和我這個做例子的日志表結(jié)構(gòu)上有所不同,約束條件、索引和默認(rèn)值都不盡相同。

只要稍加修改就可以了。

    三、用戶需要有create any table系統(tǒng)權(quán)限(不是角色里包含的權(quán)限)
   
    因為在執(zhí)行存儲過程時,由角色賦予的權(quán)限會失效, 所以執(zhí)行l(wèi)og_history的用戶一定要有DBA單獨賦予的
    create any table系統(tǒng)權(quán)限。
   
    最后在OS里定時每月一號凌晨0:00分執(zhí)行l(wèi)og_history,讓存儲過程定期分割表。
   
    假如要分割的日志表很多,模擬log_history可以寫很多類似的存儲過程來分割不同項目里的日志表。
    然后讓OS按月,按周或者不定期地執(zhí)行這些存儲過程, 治理員只要查看日志就可以了。
   
   四、其它注重事項    

       假如應(yīng)用程序有BUG,可能對在用原始日志表產(chǎn)生長期不能釋放的鎖,執(zhí)行l(wèi)og_history重命名會不成功。
      
       這時DBA可以查看數(shù)據(jù)字典:
      
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;

       假如有長期出現(xiàn)的一模一樣的列(包括登錄時間),可能是沒有釋放的鎖。

       我們要在執(zhí)行分割日志表的存儲過程前,用下面SQL語句殺掉長期沒有釋放非正常的鎖:
      
alter system kill session 'sid,serial#';

   五、結(jié)束語
  
       用上面介紹的存儲過程定期分割日志表有很大的靈活性。歷史數(shù)據(jù)不僅查詢方便,轉(zhuǎn)移和備份起來也都很輕易。
       Unix和Windows平臺的都可以使用。對服務(wù)器硬盤空間較小的中小型公司意義尤其明顯。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 镇安县| 兴安县| 休宁县| 阜阳市| 隆回县| 疏附县| 玛纳斯县| 绵竹市| 中牟县| 武陟县| 舟山市| 临高县| 正宁县| 阿荣旗| 哈巴河县| 赤壁市| 定襄县| 四平市| 长武县| 临城县| 沙田区| 宿州市| 白玉县| 井冈山市| 康乐县| 延边| 大城县| 石城县| 衡山县| 吉首市| 凉城县| 襄垣县| 阳新县| 济源市| 新蔡县| 新津县| 泊头市| 都兰县| 寿阳县| 来凤县| 剑阁县|