可以锁定触发器; 怎么会确定它是?

Ben*_*Ben 4 oracle triggers plsql

在回答中如果在我的应用程序运行时替换oracle触发器,我会错过任何更改吗?,我去查看触发器是否被INSERT语句锁定.它不是,我在互联网上找不到任何建议可以锁定触发器的东西.

如果我在一个会话中运行以下内容:

create table test_trigger (id number);
create table test_trigger_h (id number);

create or replace trigger test_trigger_t 
 after insert on test_trigger for each row
begin
  insert into test_trigger_h (id) values (:new.id);
end;    
/

insert into test_trigger
 select level
   from dual
connect by level <= 1000000;
Run Code Online (Sandbox Code Playgroud)

然后在第二个会话中尝试找出正在发生的锁定我得到以下内容:

select object_name, object_type
     , case l.block
            when 0 then 'Not Blocking'
            when 1 then 'Blocking'
            when 2 then 'Global'
       end as status
     , case v.locked_mode
            when 0 then 'None'
            when 1 then 'Null'
            when 2 then 'Row-S (SS)'
            when 3 then 'Row-X (SX)'
            when 4 then 'Share'
            when 5 then 'S/Row-X (SSX)'
            when 6 then 'Exclusive'
            else to_char(lmode)
       end as mode_held
  from v$locked_object v
  join dba_objects d
    on v.object_id = d.object_id
  join v$lock l
    on v.object_id = l.id1
  join v$session s
    on v.session_id = s.sid
       ;

OBJECT_NAME          OBJECT_TYPE          STATUS          MODE_HELD
-------------------- -------------------- --------------- ---------------
TEST_TRIGGER         TABLE                Not Blocking    Row-X (SX)
TEST_TRIGGER_H       TABLE                Not Blocking    Row-X (SX)
Run Code Online (Sandbox Code Playgroud)

根据Oracle的说法,触发器没有被锁定.

但是,如果我在INSERT语句运行时尝试替换触发器,则在语句完成(不包括提交)之后将不会替换它,这意味着触发器被锁定.

在这种情况下,触发器是否被锁定,如果是,那么如何判断它是什么?

Nic*_*nov 8

要确定是否锁定了触发器(以及任何其他存储过程),可以查询V $ ACCESS动态性能视图.

Session #1

insert into test_trigger
 select level
   from dual
connect by level <= 1000000; 

Session #2

SQL> select *
  2    from v$access
  3   where object = upper('test_trigger_t')
  4  ;


Sid  Owner  Object         Type    Con_Id 
--------------------------------------
441  HR     TEST_TRIGGER_T TRIGGER  3 
Run Code Online (Sandbox Code Playgroud)

这些类型的是库缓存引脚(库缓存锁是资源(TM锁类型)锁),需要确保在会话执行时保护对象不被修改.

--session sid # 441
insert into test_trigger
  select level
    from dual
 connect by level <= 1000000;


-- session sid #24
create or replace trigger test_trigger_t 
after insert on test_trigger for each row
begin
  insert into test_trigger_h (id) values (:new.id);
end;  

-- Session # 3
select vs.sid
     , vs.username
     , vw.event
  from v$session       vs
  join v$session_wait  vw
    on (vw.sid = vs.sid)
  join v$access        va
    on (va.owner = vs.username)
 where vs.username = 'HR'
Run Code Online (Sandbox Code Playgroud)

结果:

Sid Username Event 
--------------------------
24 HR library cache pin 
....
441 HR log file switch (checkpoint incomplete) 
Run Code Online (Sandbox Code Playgroud)

在这里我们可以看到会话#441等待日志文件切换,会话#24等待库缓存引脚.