example - trigger plsql oracle
¿Puede un disparador estar bloqueado? ¿cómo uno determinaría que es? (1)
Para determinar si un disparador (así como cualquier otro procedimiento almacenado) está bloqueado o no, se puede consultar la vista de rendimiento dinámico de 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
Esos tipos de bloqueos son pines de caché de biblioteca (los bloqueos de caché de biblioteca son bloqueos de recursos (tipo TM
de bloqueo)), necesarios para garantizar que un objeto esté protegido contra modificaciones mientras la sesión lo está ejecutando.
--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''
Resultado:
Sid Username Event
--------------------------
24 HR library cache pin
....
441 HR log file switch (checkpoint incomplete)
Aquí podemos ver que la sesión # 441 espera una conmutación de archivo de registro y la sesión # 24 espera el pin de la memoria caché de la biblioteca.
Al responder, ¿omitiré cualquier cambio si reemplazo un activador de Oracle mientras mi aplicación se está ejecutando? , Busqué para ver si el disparador estaba bloqueado por una instrucción INSERT. No fue así y no puedo encontrar nada en Internet que sugiera que se pueda bloquear un disparador.
Si ejecuto lo siguiente en una sesión:
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;
y luego, en una segunda sesión, intento averiguar qué bloqueos están teniendo, obtengo lo siguiente:
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)
Según Oracle, el disparador no está bloqueado.
Sin embargo, si intento reemplazar el activador mientras se ejecuta la instrucción INSERT, no se reemplazará hasta que se haya completado la declaración (sin incluir una confirmación), lo que implica que el desencadenador está bloqueado.
En esta situación, ¿está activado el disparador y, de ser así, cómo se determinaría que es?