网站建设| 数据库类| 图形图象| 程序设计| 现代办公| 操作系统| 考试认证| 网络技术| 软件工程| 电脑相关| 文学作品
网站开发| 网页制作| 操作系统| 图象图形| 考试认证| 数据库类| 程序设计| 硬件技术| 现代办公| 网络技术| 笑话频道
 
您的位置: 电脑书库首页-> 电脑文摘-> 数据库类-> Oracle-> 在ORACLE里用存储过程定期分割表

在ORACLE里用存储过程定期分割表
作者:佚名 来源:InterNet 加入时间:2005-1-31
相关文章
  • 夺取月薪之冠-Oracle认证!
  • Oracle数据安全面面观(2)
  • Oracle数据安全面面观(1)
  • Oracle10g数据库的创建
  • Oracle新技术对Linux意味着什么?
  • 在Oracle里设置访问多个SQL Server
  • 深入分析Oracle数据库日志文件
  • 用Linux完成Oracle自动物理备份
  • Oracle Rman/tivoli-TDP/下数据恢复到节点
  • SQL Server到Oracle连接服务器的实现
  • 相关书籍:
  • 利用 DBCA建立 Oracle 9i 资料库
  • Oracle 数据库DBA管理手册
  • Oracle 管理员手册
  • Oracle 官方文档CHM合集-SQL参考手册
  • Oracle WebServer 中文手册
  • Oracle 9i 数据库管理员指南
  • Oracle 9i 数据库管理实务讲座
  • Oracle 9I 入门基础(第02部分)
  • Oracle 9I 入门基础(第01部分)
  • Oracle 9i 官方教材
  • 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#';


    五、结束语

      用上面介绍的存储过程定期分割日志表有很大的灵活性。历史数据不仅查询方便,转移和备份起来也都很容易。Unix和Windows平台的都可以使用。对服务器硬盘空间较小的中小型公司意义尤其明显。

    [文章录入员:nancy]

    相关文章
  • 夺取月薪之冠-Oracle认证!
  • Oracle数据安全面面观(2)
  • Oracle数据安全面面观(1)
  • Oracle10g数据库的创建
  • Oracle新技术对Linux意味着什么?
  • 在Oracle里设置访问多个SQL Server
  • 深入分析Oracle数据库日志文件
  • 用Linux完成Oracle自动物理备份
  • Oracle Rman/tivoli-TDP/下数据恢复到节点
  • SQL Server到Oracle连接服务器的实现
  • 相关书籍:
  • 利用 DBCA建立 Oracle 9i 资料库
  • Oracle 数据库DBA管理手册
  • Oracle 管理员手册
  • Oracle 官方文档CHM合集-SQL参考手册
  • Oracle WebServer 中文手册
  • Oracle 9i 数据库管理员指南
  • Oracle 9i 数据库管理实务讲座
  • Oracle 9I 入门基础(第02部分)
  • Oracle 9I 入门基础(第01部分)
  • Oracle 9i 官方教材
  • 本站推荐内容

    近期主机类热搜关键词:
    美国服务器 美国服务器租用 海外服务器租用 国外服务器租用

    Oracle
    ACCESS
    MS SQL
    MySQL
    Oracle
    Foxpro
    PowerBuilder
    Sybase
    其它
    电脑教程阅读排行
    ·Oracle 常用技巧和脚本
    ·Oracle常用数据字典
    ·Oracle8 数据类型
    ·Oracle 8.1.6 for...
    ·Oracle 基本知识
    ·深入分析Oracle数据库日志文...
    ·安装Oracle后,经常使用的修...
    ·怎样快速查出Oracle数据库中...
    ·Oracle 8.0.4 for...
    ·Oracle10g数据库的创建