我的一个应用:
两个表:trace_table 保存obj的所有事件信息
status_table 保存obj当前状态(事件)信息,其obj列上建有非唯一索引
(本应为主键,因历史原因建成了非唯一索引)
一个Pro*c应用:
insert_proc 负责处理接收到的报文并insert到trace_table中
一个trigger:
t2s_trigger "before insert on trace_table for each row"工作方式,
负责根据当前插入的事件信息更新(update或insert)status_table
的状态信息,
trigger脚本如下:
CREATE OR REPLACE TRIGGER t2s_trigger BEFORE INSERT ON trace_table FOR EACH ROW
DECLARE
current_status status_table%ROWTYPE;
BEGIN
BEGIN
select * into current_status from status_table where obj = :new.obj and rownum<2; -- 一些运算 update status_table set ... where obj = :new.obj; EXCEPTION
when NO_DATA_FOUND then insert into status_table(...) values(...); return;
END; -- 其它操作END;
运行环境:该应用运行在两个环境中,处理相同的报文:
A环境:Oracle 8.0.5,insert_proc有5个并发进程
B环境:Oracle 8.1.6,insert_proc有2个并发进程现象:当关于某obj的多个报文在同一瞬间被处理时:
A环境有可能出现trace_table插入正常,而status_table没有insert或update为最新状态的情况;
B环境没发生过这种情况,
A环境也不是总是这样,看起来A环境会正常运行几个月然后忽然不正常一两个星期,
后来又自己好了(我认为上传报文的数量及同一obj的不同事件报文恰好同时处理的可能性不会有
多大的变化的)问题:1、请帮我分析一下那个trigger,是否有什么潜在的问题?
2、或者,Oracle的trigger是否真的非常可靠?
3、B环境为何没有上述情况?(或许是并发数少的缘故?)
4、A环境为何时好时坏?非常感谢!
两个表:trace_table 保存obj的所有事件信息
status_table 保存obj当前状态(事件)信息,其obj列上建有非唯一索引
(本应为主键,因历史原因建成了非唯一索引)
一个Pro*c应用:
insert_proc 负责处理接收到的报文并insert到trace_table中
一个trigger:
t2s_trigger "before insert on trace_table for each row"工作方式,
负责根据当前插入的事件信息更新(update或insert)status_table
的状态信息,
trigger脚本如下:
CREATE OR REPLACE TRIGGER t2s_trigger BEFORE INSERT ON trace_table FOR EACH ROW
DECLARE
current_status status_table%ROWTYPE;
BEGIN
BEGIN
select * into current_status from status_table where obj = :new.obj and rownum<2; -- 一些运算 update status_table set ... where obj = :new.obj; EXCEPTION
when NO_DATA_FOUND then insert into status_table(...) values(...); return;
END; -- 其它操作END;
运行环境:该应用运行在两个环境中,处理相同的报文:
A环境:Oracle 8.0.5,insert_proc有5个并发进程
B环境:Oracle 8.1.6,insert_proc有2个并发进程现象:当关于某obj的多个报文在同一瞬间被处理时:
A环境有可能出现trace_table插入正常,而status_table没有insert或update为最新状态的情况;
B环境没发生过这种情况,
A环境也不是总是这样,看起来A环境会正常运行几个月然后忽然不正常一两个星期,
后来又自己好了(我认为上传报文的数量及同一obj的不同事件报文恰好同时处理的可能性不会有
多大的变化的)问题:1、请帮我分析一下那个trigger,是否有什么潜在的问题?
2、或者,Oracle的trigger是否真的非常可靠?
3、B环境为何没有上述情况?(或许是并发数少的缘故?)
4、A环境为何时好时坏?非常感谢!
when others then
insert into status_table(...) values(...);
return;试试
select * into current_status from status_table where obj = :new.obj and rownum<2; -- 一些运算 update status_table set ... where obj = :new.obj; EXCEPTION
when NO_DATA_FOUND then insert into status_table(...) values(...); return;
END; -- 其它操作END;
看法:
1、insert的时候如果异常怎么你处理了么,那样会造成你的情况
2、update也存在这样的问题
BEGIN
select * into current_status from status_table where obj = :new.obj and rownum<2;
/*** 这里没有异常处理when NO_DATA_FOUND then的情况,如果可以保证每次取道值则可以不处理 ***/ -- 一些运算 update status_table set ... where obj = :new.obj; EXCEPTION
when NO_DATA_FOUND then
/***此处NO_DATA_FOUND 错误,其仅仅为SELECT into的异常,应该使用SQL%NOTFOUND ***/ insert into status_table(...) values(...); return;
END;
1、那句select into不能保证每次都取到值:有则update;无则insert
2、后面的when NO_DATA_FOUND then就是针对select into的