学院首页 软件应用 编程开发 创意设计 认证培训 软件论坛
ASP ASP.NET PHP JSP SQL MYSQL Java VB

您的位置:学院 >> 编程开发 >> Oracle >> 借助Oracle存储过程实现定期分割表


借助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 replacā?苨??? ????e 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平台的都可以使用。对服务器硬盘空间较小的中小型公司意义尤其明显。

技术文章快速查找

栏目导航
软件应用
·操作系统 ·杀毒防黑 ·应用软件
·聊天软件 ·网络软件  
Web开发
·ASP ·JavaScript ·CGI
·JSP ·VbScript ·Web服务器
·PHP ·XML  
开发语言
·VB ·VC ·ASP.NET
·Java ·C/C++ ·Delphi
数据库开发
·MySQL ·SQL/Access ·PowerBuilder
·Oracle ·DB2  
网站设计
·Flash ·Dreamweaver ·HTML/CSS
·Fireworks ·FrontPage  
平面设计
·Photoshop ·CorelDraw ·AutoCAD
·FreeHand ·Illustrator ·3DsMAX
媒体动画
·Director ·Authorware ·Maya
·视频处理    


相关软件 产品库推荐
·笔记本 ·台式机 ·服务器
·数码相机 ·手机 ·GPS
·DV摄像机 ·MP3 ·MP4
·CPU ·硬盘 ·内存
·主板 ·显卡 ·显示器
·打印机 ·投影机 ·路由器

还没人留言,抢个先,哈哈!
对"借助Oracle存储过程实现定期分割表"的评论 - 快速回贴
内容:
  [完成后可按Ctrl+Enter发布]

百度中 借助Oracle存储过程实现定期分割表 相关内容
Google搜索中 借助Oracle存储过程实现定期分割表 相关内容
雅虎中 借助Oracle存储过程实现定期分割表 相关内容
Sogou搜索中 借助Oracle存储过程实现定期分割表 相关内容

相关软件 最新回复帖子:

·Windows Vista 中卸载软件的不同方式
·没有mysql支持时的替代方案
·一个可以发送附件及HTML格式邮件的PHP类
·AutoCAD打造精致三维鸟笼实例详解
·Photoshop自定义水晶字特效样式
·AutoCAD三维基础实例教程
·PS为黑背景长发美女照片抠图换背
·用Photoshop自制个性摩托车贴花小经验
·轻松几步将美女照片处理为手工素描
·巧用Photoshop画笔轻松绘制创意特效


  相关软件 借助Oracle存储过程实现定期分割表相关文章
Oracle归档模式的命令及参数说明 Oracle Spatial数据加密问题的研究
一个容易忽视的Oracle数据安全问题 从Oracle到SQL Server-SQL智能翻译器
Oracle数据库异地自动备份方法介绍 高手的Oracle大批量删除数据的方法
如何保持Oracle数据库的优良性能 通过OMS来实现Oracle数据备份的方法
Oracle SQL性能优化系列介绍(下) Oracle SQL性能优化系列介绍(上)
Oracle Job任务异常原因分析及其解决 Oracle数据库中分区表的操作方法详解
用SQL*Loader将Excel数据导出到Oracle MYSQL,Oracle,SQL数据库在JSP中的驱动
不安装ORACLE客户端的系统移植方法 SQL Server 和 Oracle 常用函数对比
Oracle中捕获问题SQL解决CPU过渡消耗 在Oracle中使用PL/SQL操作COM对象
Oracle 数据库的集中复制方法浅议 基础简介:深入了解Oracle的数据字典