在项目当中,需要将某些数据记录在日志表中,以备审计或统计等。但日志表在保存过一段时间后,需要定时清理,而好多项目中,多采用数据库JOB针对每个日志表单独清理,这种方式的缺点:1)新增日志表清理开发工作量大;2)相同逻辑处理,但因清理周期不同,存在大量相同代码;3)如果屏蔽某个功能,不需要日志清理,屏蔽定时任务,开发工作量也比较大。。。
解决方法:可以将清理日志表相关的表名和清理周期等动态参数保存在数据库单独日志清理配置表中集中配置,相同逻辑处理放在Oracle存储过程中实现。这种实现方式的好处:1)新增日志表清理只需要增加日志清理配置表初始化脚本;2)日志清理逻辑放入一个存储过程中实现,新增、修改、删除日志清理,将风险降低最小;3)日志清理表中保存数据清晰,清理日志时间周期可动态配置。。。
见日志清理表的数据模型,T_ClearLogConfig。
column | 字段长度 | nullable | comment |
tableName | varchar2(30) | NO | 清理日志表名 |
timeColumn | varchar2(30) | NO | 清理日志表的时间字段标识 |
saveDays | number | NO | 日志保存天数 |
timeType | varchar2(2) | NO | 日志表时间类型1:字符型 2:日期型 |
timeFormat | varchar2(30) | YES | 如果时间类型为字符型,该字段保存具体的时间格式 如:YYYY-MM-DD HH24:MI:SS |
description | varchar2(600) | YES | 该字段不被使用,只保存描述,方便别人理解 |
将需要删除的日志表信息配置在上述表中,然后新增存储过程,根据上述表配置内容,执行清理操作。然后配置定时任务,在每天凌晨触发该存储过程。
存过实现思路如下(注意:实例中并没有记录异常信息,在项目当中,务必增加,否则存储过程执行异常,问题很难发现和定位)
create or replace procedure p_job_clearLog
as
v_tableName t_clearLogConfig.tableName%type;
--其他变量类似定义,不再一一列举
cursor c_clearLog is
select t.tableName, t.timeColumn, t.saveDays, t.timeType, t.timeFormat
from t_clearLogConfig t;
begin
open c_clearLog;
loop
begin --针对每一次清理日志进行异常捕获,防止清理某个日志失败,导致其他日志不能清理。应该将fetch into和exit语句放在begin外执行,sorry。
fetch c_clearLog into
v_tableName, v_timeColumn, v_saveDays, v_timeType, v_timeFormat;
exit when c_clearLog%notFound;
if v_timeType = '1' then --如果时间类型为字符型
v_sql := 'delete from ' || v_tableName || ' where :timeColumn < to_char(trunc(sysdate - :saveDays), :timeFormat)';
execute immediate v_sql using v_timeColumn, v_saveDays, v_timeFormat;
commit;
elsif v_timeType = '2' then --时间类型为日期型
v_sql := 'delete from ' || v_tableName || ' where :timeColumn < sysdate - :saveDays';
execute immedidate v_sql using v_timeColumn, v_saveDays;
commit;
end if;
exception
when others then
rollback;
--记录异常日志
end loop;
close c_clearLog;
exception
rollback;
if c_clearLog%isOpen then
close c_clearLog;
end if;
--记录日志
end p_job_clearJob;
思考其他几个问题:
1)以上日志清理是以天为单位清理,但一般日志清理的周期都比较长,半年或者一年或更长时间清理一次,如果修改为按月为单位执行呢?
2)在项目当中,好多日志保存在日志表时,日志表名是动态的,多以时间动态变化,如保存时日志名为t_log_201212,对这种情况如何修改实现呢?
说明:
1)可以在日志清理表中增加是否清理标识,如果为清理标识,则清理该日志,否则不清理,可动态配置某日志是否清理。
2)该文章只是个人的一些想法杂谈,如果您有什么好的想法或意见,欢迎交流。