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_segmentswhere 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 replacā?苨??? ????e 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_timefrom v$locked_object t1,v$session t2where t1.session_id=t2.sid order by t2.logon_time;

  

如果有长期出现的一模一样的列(包括登录时间),可能是没有释放的锁。

我们要在执行分割日志表的存储过程前,用下面SQL语句杀掉长期没有释放非正常的锁:

  alter system kill session 'sid,serial#';

  

五、结束语

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

转载于:https://www.cnblogs.com/chinhr/archive/2007/06/18/787745.html

借助Oracle存储过程实现定期分割表相关推荐

  1. ORACLE存储过程运行报“ora-00942表或视图不存在”、“ORA-01031:权限不足”的解决方式

    目录: 一.案例 二.思索过程 三.解决方案 四.后记 正文 一.案例: 在userA用户下书写存储过程如下: create or replace procedure sp_test is v_str ...

  2. ORACLE存储过程中打印所有表数据的方法

    前几天面试的时候,人家出了个面试题,说通过存储过程打印表里面的数据,从没做过纸上手写存储过程的,结果一脸懵逼,估计要凉,只能怪自己平时不细心吧,下来研究了之后做个记录,结构和过程都不复杂. 过程中参考 ...

  3. oracle 定时清理表数据,关于Oracle存储过程和调度器实现自动对数据库过期数据清除的问题...

    简介 数据库中的某些数据不一定要长期保存,例如:日志等数据.当保存一定时间后,系统允许删除所以系统需要定期删除那些已经过期的数据. 实现原理 1张表(SYS_DBA_CONFIG).1个Job定时器( ...

  4. Oracle存储过程中如何根据指定的参数判断该参数的值否存在数据表中:

    摘要:最近项目中用到了Oracle存储过程,所以就自己尝试着写了下,下面我把我遇到的问题描述一下:就是在我处理解析Clob字段中的xml字符串的时候,有个需求就是根据指定的主键参数,来判断该参数的值是 ...

  5. oracle存储过程建表写法,用oracle存储过程创建表

    create or replace procedure createtable(tname in varchar2) is sqlTEXT varchar2(400); v_createsql var ...

  6. ORACLE存储过程批量建表-笔记

    目录 一.存储过程简介及基础语法 二.建表语句分析 三.编写存储过程并测试 四.本次所遇到问题记录 五.附录 一.存储过程简介及基础语法 (一)定义 存储过程是一组为了完成特定功能的SQL语句,经编译 ...

  7. oracle复制另一个字段,【学习笔记】Oracle存储过程 表中列不同时动态复制表中数据到另一个表中...

    天萃荷净 分享一篇关于Oracle存储过程实现表之间数据复制功能.两表中列不同,动态的将一表中的数据复制到另一个表中案例 因为要用到回收站功能,删除一条记录,要先放到一个delete表中,以便以后恢复 ...

  8. 创建emp表 oracle,Oracle中创建和管理表详解

    Oracle中创建和管理表详解 更新时间:2013年08月01日 15:44:16   作者: 以下是对Oracle中的创建和管理表进行了详细的分析介绍,需要的朋友可以过来参考下 SQL> /* ...

  9. Oracle查看用户所在的表空间

    oracle 查看表空间有哪些表 select * from dba_tables where tablespace_name='表空间名',注意表空间名大小写敏感. select table_nam ...

最新文章

  1. CYQ.Data 轻量数据层之路 使用篇五曲 MProc 存储过程与SQL(十六)
  2. python编程 语言-Python——最美丽的编程语言
  3. php递归复制文件内容,PHP递归复制整个文件夹
  4. asp.net 2.0下嵌套masterpage页的可视化编辑
  5. Spring boot的Maven配置依赖
  6. windowswps怎么以文件形式发送_wps怎么以文件形式分享
  7. MinGW —— Minimalist GNU for Windows、Cygwin —— Windows 下的类 unix 系统
  8. AFR 去嵌 Deeembedding 软件工具
  9. 百度文库内容复制文字解决方法
  10. 真实网络环境下使用易邮搭建网络邮件服务器并测试通过
  11. 三菱服务器显示b01,MR-JE-B三菱伺服驱动器的启动事项
  12. HTML中,使用hover属性完成鼠标悬停切换图片效果
  13. 苹果与宝马和奔驰关于自动驾驶汽车的谈判告吹,退而求其次选择与大众汽车合作
  14. OpenGl运行窗口出现纯白色
  15. STM32毕业设计题目大全
  16. ARM微控制器与嵌入式系统 基础知识
  17. 复选框CheckBox
  18. LeetCode Word Break II
  19. 以太坊或ERC20转账查询(Java版本)
  20. PCB画可插器件封装的一些技巧(以LEM传感器LV25-PSP5为例

热门文章

  1. 【Java Web开发指南】有状态会话Bean(SLSB) 和无状态会话Bean(SFSB)的区别
  2. 【django轻量级框架】一个Github用户检索信息网站(解析和代码)
  3. python【力扣LeetCode算法题库】945- 使数组唯一的最小增量
  4. python【蓝桥杯vip练习题库】ADV-183分苹果(差分数组 离线区间)
  5. python【蓝桥杯vip练习题库】BASIC-19完美的代价(贪心算法)
  6. 如何从SEO优化角度设计网站导航栏?
  7. mysql表误删回复_mysql 找回误删表的数据方法(必看)
  8. vnr光学识别怎么打开_水晶光电:光学元件需求向好,光学创新打开成长新空间,未来可期...
  9. u盘文件看得见却打不开_win7下u盘文件打不开怎么办 win7下u盘文件打不开解决方法...
  10. map和foreach的区别和应用场景_浅析项目中常用的 VO、DTO、DO、PO的概念、区别和用处...