miércoles, 21 de mayo de 2014

¿Un Problema con V$FILESTAT?

Hallé la idea para este ejemplo aquí. Antes de empezar, quiero explicar los nombres de tres de las columnas en V$FILESTAT:

PHYRDS (Physical Reads) = El número de veces que Oracle ha leído un archivo.
 
PHYBLKRD (Physical Block Reads) = El número de bloqueos que Oracle ha leído de un archivo.

 
SINGLEBLKRDS (Single Block Reads) = El número de veces que Oracle ha leído un solo bloqueo de un archivo.


Ejecuté el comando SQL siguiente en Oracle versión 11.1.0.6: 

SQL> l
  1  select file#, phyrds, phyblkrd, singleblkrds
  2  from v$filestat
  3  where phyrds = phyblkrd
  4* and singleblkrds != phyrds
SQL> /
 
     FILE#     PHYRDS   PHYBLKRD SINGLEBLKRDS
---------- ---------- ---------- ------------
         3       7467       7467         7457
         5        113        113          103
         8        118        118          108
        19        362        362          352
        20        297        297          287
        23        116        116          106
        25        113        113          103
 
7 rows selected.
 
SQL>

En cada línea, PHYRDS = PHYBLKRD, es decir que Oracle ha leído un solo bloqueo cada vez. Así, deben haber sido SINGLEBLKRDS pero no lo son porque el valor de SINGLEBLKRDS es diferente cada vez.


sábado, 10 de mayo de 2014

Oracle no Ejecuta un Disparador AFTER DELETE Tras Hacer un Truncate

En este ejemplo, quiero mostrar que Oracle no ejecute un disparador AFTER DELETE después de hacer un TRUNCATE. Lo probé en Oracle 11.2. Para empezar, creé una tabla:

SQL> create table tab1 (my_name varchar2(10))
  2  /

Tabla creada.

SQL>

Luego inserté una fila en la tabla:

SQL> insert into tab1 values ('Andrew')
  2  /

1 fila creada.

SQL> commit
  2  /

Confirmación terminada.

SQL> select * from tab1
  2  /

MY_NAME
----------
Andrew

SQL>

Entonces creé una segunda tabla: 

SQL> create table tab2 (my_name varchar2(10))
  2  /

Tabla creada.

SQL>

Creé un disparador para insertar filas en TAB2 tras borrarlas de TAB1:

SQL> create or replace trigger trig1
  2  after delete on tab1
  3  for each row
  4  begin
  5  insert into tab2 (my_name) values (:old.my_name);
  6  end;
  7  /
 
Disparador creado.


SQL>

Para probar el disparador, empleé un DELETE para borrar la fila de TAB1. La fila apareció en TAB2:

SQL> delete tab1
  2  /

1 fila suprimida.

SQL> select * from tab1
  2  /

ninguna fila seleccionada

SQL> select * from tab2
  2  /

MY_NAME
----------
Andrew

SQL>

Ejecuté un ROLLBACK y la fila volvió de TAB2 a TAB1:

SQL> rollback
  2  /
 
Rollback terminado.
 
SQL> select * from tab1
  2  /
 
MY_NAME
----------
Andrew
 
SQL> select * from tab2
  2  /
 
ninguna fila seleccionada


SQL>

Repetí la prueba con TRUNCATE: 

SQL> truncate table tab1
  2  /
 
Tabla truncada.


SQL>

La fila desapareció de TAB1:

SQL> select * from tab1
  2  /
 
ninguna fila seleccionada


SQL>

... pero Oracle no ejecutó el disparador y la fila no apareció en TAB2:

SQL> select * from tab2
  2  /
 
ninguna fila seleccionada
 

SQL>

... y tras hacer un ROLLBACK, la fila no volvió a TAB1 porque TRUNCATE es DDL y incluye un COMMIT:

SQL> rollback
  2  /
 
Rollback terminado.
 
SQL> select * from tab1
  2  /
 
ninguna fila seleccionada
 
SQL> select * from tab2
  2  /
 
ninguna fila seleccionada
 
SQL> 


En inglés / in English