在ORACLE里用存储过程定期分割表
来源:互联网 发布:2016网络女歌手 编辑:程序博客网 时间:2024/05/16 17:50
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_nameinvarchar2, target_namein varchar2, timesin outnumber) 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); timesnumber; 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平台的都可以使用。对服务器硬盘空间较小的中小型公司意义尤其明显。
程序员特区
http://coderarea.net/html/shujukukaifa/Oracle/2009/0311/60264.html
- 在ORACLE里用存储过程定期分割表
- 在ORACLE里用存储过程定期分割表
- 在ORACLE里用存储过程定期分割表
- 在ORACLE里用存储过程定期分割表
- 在ORACLE里用存储过程定期分割表
- 在ORACLE里用存储过程定期分割表
- 在ORACLE里用存储过程定期分割表
- 在ORACLE里用存储过程定期分割表〔转〕
- 用存储过程定期分割表
- 在oracle里用java写存储过程
- oracle日志定期清理存储过程
- oracle中定期执行存储过程
- 在java里使用oracle存储过程应注意的
- oracle中建立job定期运行存储过程总结
- oracle中建立job定期运行存储过程总结
- oracle中建立job定期运行存储过程总结
- oracle中建立job定期运行存储过程总结
- oracle中建立job定期运行存储过程总结
- 沉积的开始
- dhtmlxTree总结
- 零点
- 【ADSP-BF561 EZ-KIT Lite】PROGRAMMABLE FLAGS(PFx)
- 冰箱谷歌 Fridge Googling
- 在ORACLE里用存储过程定期分割表
- [双语阅读]伦敦特拉法加广场上演“活体雕塑”展
- 中国联通 Wo分业务系列广告视频
- 人民币“跨境结算” cross-border settlement
- In the pink 精力充沛
- [英语阅读]日本服务业员工每日扫描微笑
- wince 读取DSK容量
- 商务英语:广告法则
- Why we love who we love 打破砂锅爱到底