Está en la página 1de 7

Disparadores (trigger)

Un disparador o trigger es un código procedimental o procedimiento que se ejecuta automáticamente


en respuesta de ciertos eventos sobre una tabla en particular. Un trigger es usado normalmente para
mantener la integridad de la información en una base de datos. Por ejemplo, cuando una nueva tupla se
agrega a la tabla empleados, nuevas tuplas deberían ser creadas en las tablas de impuestos, vacaciones
y salarios.

Normalmente los disparadores son utilizados para las acciones delete, insert y update, estos deben de
ser utilizados con cuidado si se utilizan otros comandos dml de actualización dentro del trigger ya que
puede darse una recursión de disparadores creando comportamientos no deseados.

A continuación se muestra un ejemplo de como crear un trigger en oracle:

CREATE OR REPLACE TRIGGER tri_check_nulls


BEFORE INSERT ON TABLE1
FOR EACH ROW WHEN (new.CODE is NULL)
DECLARE
VIEW_CODE INTEGER;
BEGIN

VIEW_CODE := TO_NUMBER(SUBSTR(new.COMMENT, INSTR(new.COMMENT, '-', -1, 1) + 1));

select distinct v.CODE, v.PARTNER, v.COUNTRY


into :new.CODE, :new.PARTNER, :new.COUNTRY
from VIEW1 v
where v.CODE = VIEW_CODE;

END;
/

El disparador anterior se crea para el comando “insert”, cuando este se realiza en la tabla “TABLE1”.
Paquetes pl-sql
Los paquetes en PL/SQL tienen el objetivo de agrupar procedimientos y funciones de forma lógica. De
esta manera, se consigue agrupar en un único objeto, toda la casuística asociada a un determinado tipo
de tarea. Por ejemplo, si tenemos un conjunto de procedimientos y funciones para realizar cálculos
matemáticos complejos, los podemos poner en un paquete.

La ventaja de los paquetes es que la primera vez que se invoca, es cargado en memoria, por lo que las
siguientes veces ya no será necesario hacerlo de nuevo. Además, el paquete mantiene una copia en
memoria para todos los usuarios. Otra ventaja, es que podemos encapsular procedimientos y funciones
que no forman parte de la interfaz de usuario. Podemos ocultar ciertos objetos y solo hacer públicos los
que se necesiten. También se permite la sobrecarga dentro de los paquetes. El paquete se divide en
especificación y cuerpo.

El paquete se compone de dos definiciones, la especificación y el cuerpo del paquete.

La especificación nos muestra todos los procedimientos y funciones que van a ser públicos, también las
variables o contantes que van a ser globales y pueden ser accedidas fuera del paquete. La sintaxis de
creación de especificación es la siguiente:

CREATE [OR REPLACE] PACKAGE nombre_paquete


IS | AS
declaraciones de variables, cursores...
subprogramas en PLSQL
END nombre_paquete

Para el cuerpo del paquete, que contiene el código del paquete, define las funciones y procedimientos
públicos y privados. La sintaxis para el cuerpo del paquete es la siguiente:

CREATE [OR REPLACE] PACKAGE BODY nombre_paquete


IS | AS
declaraciones de variables, cursores...
subprogramas en PLSQL
END nombre_paquete
Concurrencia.
El tema de concurrencia corresponde al tema principal de la administración de transacciones. El término
concurrencia se refiere a la característica de que muchas transacciones accedan a la misma base de
datos a la vez. Esto lleva a que el sistema gestor de base de datos (DBMS) contenga mecanismos para el
control de concurrencia, para asegurarse que las transacciones no interfieran unas con otras. Y esto nos
trae al siguiente tema.

Los tres problemas de concurrencia.


Si alguna transacción interfiere en la ejecución de otra, pueden llegar a obtenerse resultados no
deseados al finalizar las transacciones, a pesar de que las transacciones sean correctas por si mismas. Lo
que llega a producir estos problemas son las intercalaciones que suceden entre las operaciones de las
transacciones correctas. Estos problemas son los siguientes:

1. La actualización perdida.
2. Dependencia no confirmada
3. El análisis inconsistente.

1. Actualización perdida
En este caso, ambas transacciones leen un dato y luego trabajan con el dato que ambas obtuvieron,
luego de realizar las operaciones necesarias ambas actualizan el dato, una después de la otra, por lo que
la segunda transacción, eliminará la actualización que realizó la primera transacción. Esto se puede ver
en la siguiente ilustración:

La transacción A pierde una actualización en el tiempo 4


La dependencia no confirmada
Este problema se da al permitir que una transacción realice una lectura o actualice una tupla que ha sido
actualizada por otra transacción pero que aún no ha sido confirmada (commit) por la misma
transacción. Por lo que existe la posibilidad de que la transacción deshaga los cambios que ha realizado
(rollback) y por lo tanto, la primera transacción habrá utilizado datos que ya no existen.

La transacción A depende de valores no confirmados en tiempo 2

El análisis inconsistente
En este caso se dice que A ha visto un estado inconsistente y por lo tanto ha realizado un análisis
inconsistente, observe la figura y note que mientras la transacción A esta sumando cuentas, la
transacción B esta realizando una transferencia de la cuenta 3 a la 1, el resultado de A es obviamente
incorrecto. A diferencia del ejemplo anterior B ya ha confirmado sus actualizaciones antes de que A lea
la cuenta 3

La transacción A realiza un análisis inconsistente


Bloqueos:
Los problemas de concurrencia pueden ser resueltos por medio de la técnica de bloqueos, esto se basa
en que cada transacción debe asegurarse que ninguna otra transacción pueda acceder a los elementos
que esta utilizando, y para esto, adquiere un bloque sobre el objeto, para impedir que otras
transacciones lo cambien, logrando que este se encuentre estable durante toda la ejecución de la
transacción.

Forma en que funcionan los bloqueos:

1. Supongamos dos tipos de bloqueos: exclusivos (x) y compartidos (s) o bien bloqueos de escritura
y lectura respectivamente. (En este momento vamos a suponer que existen solo este tipo de
bloqueos aunque existen otros que veremos mas adelante en el curso)
2. Si una transacción coloca en una tupla un bloqueo X, se rechazara cualquier otro bloqueo de
otra transacción.
3. Si la transacción A coloca un bloqueo S en una tupla sucederá lo siguiente:
a. Se rechazara cualquier otro bloqueo X sobre la tupla de otra transacción.
b. Se aceptará cualquier bloqueo S sobre la tupla de otra transacción.

Estas reglas se resumen fácilmente por medio de la matriz de compatibilidad de tipos de bloqueo:

X S -
X No No Si
S No Si Si
- Si Si Si

Dados estos tipos de bloqueo y sus compatibilidades presentamos el “protocolo de acceso a datos” o
“protocolo de bloqueo” los cuales se utilizan para garantizar que no ocurra ninguno de los problemas de
concurrencia.

1. Si una transacción desea recuperar datos primero debe adquirir un bloqueo S


2. Si una transacción desea actualizar datos primero debe adquirir un bloqueo X, si esta ya tiene un
bloqueo S lo debe de cambiar a bloqueo X

Implícitamente cada vez que se recupera una tupla se hace un bloqueo S, y cada vez que se hace una
actualización (update, delete, insert , estos con algunos pequeños cambios que no se incluyen por el
momento) se realiza un bloqueo X.

3. Cuando un bloqueo de la transacción B entra en conflicto con un bloqueo de la transacción A, B


debe esperar hasta que A libere los bloqueos.
4. Los bloqueos se mantienen hasta que se llega al commit o rollback.
Ahora veremos la forma en que estos protocolos solucionan los problemas clásicos de la concurrencia:

Actualización perdida:
En el siguiente caso ambas transacciones al inicio solicitan un bloqueo de tipo S, al entrar la transacción
A en el código de actualizar, se intenta un bloqueo X pero este no es compatible con el bloqueo S de la
transacción B asi que debe esperar a que B libere el bloqueo S. Por razón similar cuando la transacción
B intenta realizar un bloqueo X no es permitido por el bloqueo S de la transacción A.
El bloqueo por lo tanto resuelve el problema de la actualización perdida pero se da un nuevo problema
llamado bloqueo mortal (deadlock)

Dependencia no confirmada
En este caso el bloqueo se realiza al principio por la transacción B al actualizar t por medio de un
bloqueo X, cuando la transacción A intenta adquirir un bloqueo S, dado que no es compatible, debe de
esperar hasta que B libere los bloqueos de t. Mientras esto sucede la transacción A se encuentra en
espera, hasta que B realiza un commit/rollback que liberan los bloqueos de los objetos y A puede
continuar. El método soluciona el problema de la dependencia no confirmada.
Análisis inconsistente:
La solicitud de actualización(x) de B sobre ACC1 entra en conflicto con el bloqueo S que ya tiene A, y por
esto, B entra en un estado de espera, de igual forma la petición de leer de ACC3 en A no es aceptada
debido al bloqueo que ya tiene B debido a la segunda operación en ACC3.

Por lo tanto, no se da el análisis inconsistente, pero se produce el bloqueo mortal.

Bloqueo Mortal:
El bloqueo mortal es una situación en la cual dos transacciones quedan en estados simultáneos de
espera, en la cual cada una de ellas se encuentra esperando que otra de las transacciones libere el
recurso que desea bloquear. Este tipo de bloqueo puede involucrar a dos o más transacciones.

Cuando esto ocurre el sistema normalmente lo detecta por medio del un ciclo en el “grafo de espera”.
Para eliminar el bloqueo mortal se debe seleccionar una de las transacciones del conflicto y deshacerla,
con lo cual liberara sus bloqueos y eliminará el bloqueo mortal. Algunas bases de datos no detectan
automáticamente los bloqueos mortales, sino tienen una cuota de tiempo, pasada la cual si la base de
datos no realiza una actividad o no finaliza alguna transacción se considera bloqueada mortalmente.

El enfoque de terminar una transacción al seleccionarla debe de ser realizado por el programador, dado
el criterio y punto de vista de este, siempre es preferible ocultar el problema ante el usuario final, por
razones obvias.

También podría gustarte