我的一个应用:
两个表: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环境为何时好时坏?非常感谢!

解决方案 »

  1.   

    To wupangzi(无本之木):你能简单介绍一下你的应用的情况吗?
      

  2.   

    我听说过触发器不太稳定,但没仔细研究过,有可能是oracle的漏洞。不过你可以检查是否“update status_table set ... where obj = :new.obj;”语句出现其它错误,添加一句:
    when others then
      insert into status_table(...) values(...);
      return;试试
      

  3.   

    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;
    看法:
    1、insert的时候如果异常怎么你处理了么,那样会造成你的情况
    2、update也存在这样的问题
      

  4.   

    To 大家:我觉得:如果对status_table的操作出错的话,那么触发该trigger的对trace_table表的insert语句也会出错的,它们在同一个事务中,应该同时成功或同时失败呀,而现在出现的是insert trace_table是成功的。另外To crazycaishen(菜神):你说的“我听说过触发器不太稳定,但没仔细研究过,有可能是oracle的漏洞”,有没有什么资料或什么论坛上有讨论?
      

  5.   


    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;
      

  6.   

    To andzen(阿风):
    1、那句select into不能保证每次都取到值:有则update;无则insert
    2、后面的when NO_DATA_FOUND then就是针对select into的