7. TCL (Transaction Control Language)
Introducción al TCL
Section titled “Introducción al TCL”El Lenguaje de Control de Transacciones (Transaction Control Language o TCL) es un subconjunto de SQL utilizado para gestionar los cambios realizados por las sentencias DML (Data Manipulation Language). TCL permite a los usuarios agrupar un conjunto de operaciones en unidades lógicas de trabajo llamadas transacciones, que pueden ser confirmadas o revertidas como una unidad.
Características principales de las transacciones
Section titled “Características principales de las transacciones”- Atomicidad: Una transacción se ejecuta por completo o no se ejecuta en absoluto
- Consistencia: Una transacción lleva la base de datos de un estado consistente a otro estado consistente
- Aislamiento: Las transacciones se ejecutan de forma aislada unas de otras
- Durabilidad: Una vez confirmada una transacción, sus cambios son permanentes
COMMIT - Confirmación de transacciones
Section titled “COMMIT - Confirmación de transacciones”El comando COMMIT se utiliza para hacer permanentes los cambios realizados durante la transacción actual.
Sintaxis básica
Section titled “Sintaxis básica”-- Sintaxis básicaCOMMIT [WORK] [COMMENT 'texto_comentario'];
-- Ejemplo simpleINSERT INTO empleados (empleado_id, nombre, apellido) VALUES (101, 'Juan', 'Pérez');UPDATE departamentos SET presupuesto = presupuesto + 10000 WHERE departamento_id = 20;COMMIT; -- Confirma ambas operacionesComportamiento del COMMIT
Section titled “Comportamiento del COMMIT”-
Hace permanentes los cambios
- Los cambios realizados por las sentencias DML se guardan permanentemente en la base de datos
- Los cambios son visibles para otras sesiones
-
Libera bloqueos
- Se liberan todos los bloqueos adquiridos durante la transacción
- Otros usuarios pueden acceder a los datos modificados
-
Establece un punto de guardado
- Se establece un punto de guardado implícito
- Finaliza la transacción actual y comienza una nueva
-
Libera recursos
- Se liberan los recursos del sistema utilizados para la transacción
- Se eliminan los datos de deshacer (undo) asociados a la transacción
Tipos de COMMIT
Section titled “Tipos de COMMIT”-- COMMIT simpleINSERT INTO clientes (cliente_id, nombre) VALUES (1001, 'Empresa ABC');COMMIT;
-- COMMIT con comentario (para auditoría)UPDATE productos SET precio = precio * 1.05 WHERE categoria = 'Electrónica';COMMIT COMMENT 'Incremento de precios 5% en electrónica';-- COMMIT FORCE: confirma una transacción en una base de datos distribuida-- incluso si algunas bases de datos no están disponiblesCOMMIT FORCE '25.32.87';
-- COMMIT WRITE: controla cómo se escriben los cambios en el redo log-- IMMEDIATE: escribe inmediatamente (más seguro)-- BATCH: agrupa escrituras (mejor rendimiento)COMMIT WRITE IMMEDIATE NOWAIT;COMMIT implícito
Section titled “COMMIT implícito”Oracle realiza un COMMIT implícito en los siguientes casos:
- Cuando se ejecuta un comando DDL (CREATE, ALTER, DROP, etc.)
- Cuando se ejecuta un comando DCL (GRANT, REVOKE)
- Cuando se cierra normalmente una sesión (EXIT o QUIT)
- Cuando se ejecuta un comando SET AUTOCOMMIT ON
ROLLBACK - Reversión de cambios
Section titled “ROLLBACK - Reversión de cambios”El comando ROLLBACK se utiliza para deshacer los cambios realizados durante la transacción actual que aún no han sido confirmados.
Sintaxis básica
Section titled “Sintaxis básica”-- Sintaxis básicaROLLBACK [WORK] [TO [SAVEPOINT] nombre_savepoint];
-- Ejemplo simpleINSERT INTO empleados (empleado_id, nombre, apellido) VALUES (102, 'María', 'Gómez');UPDATE departamentos SET presupuesto = presupuesto - 5000 WHERE departamento_id = 30;
-- Si algo sale mal o se detecta un errorROLLBACK; -- Revierte ambas operacionesComportamiento del ROLLBACK
Section titled “Comportamiento del ROLLBACK”-
Deshace los cambios
- Revierte todos los cambios realizados por las sentencias DML desde el último COMMIT o desde el inicio de la transacción
- Los datos vuelven a su estado anterior
-
Libera bloqueos
- Se liberan todos los bloqueos adquiridos durante la transacción
- Otros usuarios pueden acceder a los datos
-
Elimina savepoints
- Se eliminan todos los savepoints establecidos durante la transacción
-
Finaliza la transacción
- Termina la transacción actual y comienza una nueva
ROLLBACK parcial
Section titled “ROLLBACK parcial”Utilizando savepoints, es posible realizar un ROLLBACK parcial, deshaciendo solo una parte de la transacción.
-- Iniciar transacciónINSERT INTO clientes (cliente_id, nombre) VALUES (1002, 'Empresa XYZ');
-- Establecer un savepointSAVEPOINT despues_cliente;
-- Continuar la transacciónINSERT INTO pedidos (pedido_id, cliente_id, total) VALUES (5001, 1002, 1500);INSERT INTO pedidos (pedido_id, cliente_id, total) VALUES (5002, 1002, 2500);
-- Si hay un problema con los pedidosROLLBACK TO SAVEPOINT despues_cliente; -- Deshace solo las inserciones de pedidos
-- Continuar con la transacciónINSERT INTO pedidos (pedido_id, cliente_id, total) VALUES (5003, 1002, 3000);
-- Confirmar toda la transacciónCOMMIT;ROLLBACK implícito
Section titled “ROLLBACK implícito”Oracle realiza un ROLLBACK implícito en los siguientes casos:
- Cuando se produce un fallo del sistema
- Cuando se cierra anormalmente una sesión (p. ej., por un error de red)
- Cuando se produce un error grave durante la ejecución de una sentencia
SAVEPOINT - Puntos de guardado intermedios
Section titled “SAVEPOINT - Puntos de guardado intermedios”El comando SAVEPOINT establece un punto de guardado dentro de la transacción actual, permitiendo deshacer parte de una transacción sin tener que deshacer toda la transacción.
Sintaxis básica
Section titled “Sintaxis básica”-- Sintaxis básicaSAVEPOINT nombre_savepoint;
-- Ejemplo simpleINSERT INTO empleados (empleado_id, nombre) VALUES (103, 'Carlos');SAVEPOINT sp_despues_empleado;
INSERT INTO departamentos (departamento_id, nombre) VALUES (50, 'Innovación');
-- Si hay un problema con la inserción del departamentoROLLBACK TO SAVEPOINT sp_despues_empleado;
-- Continuar con la transacciónINSERT INTO departamentos (departamento_id, nombre) VALUES (51, 'Investigación');COMMIT;Características de los savepoints
Section titled “Características de los savepoints”- Se pueden crear múltiples savepoints dentro de una transacción
- Los savepoints permiten un control más granular de las transacciones
- Si se crea un savepoint con el mismo nombre que uno existente, el nuevo savepoint reemplaza al anterior
- Los savepoints se eliminan automáticamente cuando se ejecuta un COMMIT o un ROLLBACK completo
Gestión de savepoints múltiples
Section titled “Gestión de savepoints múltiples”-- Iniciar transacciónDELETE FROM empleados WHERE departamento_id = 10;SAVEPOINT sp_despues_eliminar_dept10;
UPDATE empleados SET salario = salario * 1.1 WHERE departamento_id = 20;SAVEPOINT sp_despues_actualizar_dept20;
INSERT INTO historial_cambios (descripcion) VALUES ('Actualización de salarios dept 20');SAVEPOINT sp_despues_historial;
-- Si hay un problema con la inserción en el historialROLLBACK TO SAVEPOINT sp_despues_actualizar_dept20;
-- Si hay un problema con la actualización de salariosROLLBACK TO SAVEPOINT sp_despues_eliminar_dept10;
-- Si todo está bienCOMMIT;Manejo de transacciones en Oracle XE
Section titled “Manejo de transacciones en Oracle XE”Oracle Database Express Edition (XE) es una versión gratuita de Oracle Database con algunas limitaciones, pero el manejo de transacciones funciona igual que en las versiones estándar.
Configuración de transacciones
Section titled “Configuración de transacciones”-- Verificar el modo de transacción actualSHOW AUTOCOMMIT;
-- Activar el modo autocommit (cada sentencia es una transacción)SET AUTOCOMMIT ON;
-- Desactivar el modo autocommit (modo manual, recomendado)SET AUTOCOMMIT OFF;-- Consultar parámetros relacionados con transaccionesSELECT name, value FROM v$parameterWHERE name LIKE '%commit%' OR name LIKE '%undo%';
-- Ver el tamaño máximo de undoSELECT name, value FROM v$parameter WHERE name = 'undo_retention';Monitoreo de transacciones
Section titled “Monitoreo de transacciones”-- Ver transacciones activasSELECT xid, status, start_time, log_io, phy_ioFROM v$transaction;
-- Ver sesiones con transacciones pendientesSELECT s.sid, s.serial#, s.username, s.status, t.used_ublk, t.start_timeFROM v$session s, v$transaction tWHERE s.saddr = t.ses_addr;
-- Ver bloqueos de transaccionesSELECT l.session_id, s.username, l.lock_type, l.mode_held, l.mode_requestedFROM v$lock l, v$session sWHERE l.session_id = s.sidAND l.lock_type = 'TX';Limitaciones en Oracle XE
Section titled “Limitaciones en Oracle XE”Oracle XE tiene algunas limitaciones que pueden afectar a las transacciones:
- Límite de uso de memoria (2GB)
- Límite de almacenamiento (12GB en Oracle XE 18c)
- Límite de uso de CPU (hasta 2 cores)
Estas limitaciones pueden afectar al rendimiento de las transacciones grandes, pero no a su funcionalidad básica.
Niveles de aislamiento de transacciones
Section titled “Niveles de aislamiento de transacciones”Oracle soporta diferentes niveles de aislamiento que determinan cómo interaccionan las transacciones concurrentes.
Configuración del nivel de aislamiento
Section titled “Configuración del nivel de aislamiento”-- Establecer el nivel de aislamiento para la sesión actualSET TRANSACTION ISOLATION LEVEL READ COMMITTED;SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- Establecer el nivel de aislamiento para una transacción específicaSET TRANSACTION ISOLATION LEVEL READ COMMITTED;SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;Niveles de aislamiento disponibles
Section titled “Niveles de aislamiento disponibles”| Nivel | Descripción | Problemas que previene |
|---|---|---|
| READ COMMITTED | Nivel predeterminado. Solo ve datos confirmados por otras transacciones | Lecturas sucias |
| SERIALIZABLE | Mayor nivel de aislamiento. Ve un snapshot de los datos al inicio de la transacción | Lecturas sucias, lecturas no repetibles, lecturas fantasma |
| READ ONLY | Similar a SERIALIZABLE, pero no permite modificaciones | Lecturas sucias, lecturas no repetibles, lecturas fantasma |
Transacciones distribuidas
Section titled “Transacciones distribuidas”Las transacciones distribuidas involucran múltiples bases de datos y utilizan el protocolo de commit en dos fases (2PC) para garantizar la consistencia.
Configuración de transacciones distribuidas
Section titled “Configuración de transacciones distribuidas”-- Crear un enlace de base de datos (database link)CREATE DATABASE LINK remote_db CONNECT TO usuario IDENTIFIED BY contraseña USING 'conexion_tns';
-- Iniciar una transacción distribuidaINSERT INTO empleados VALUES (104, 'Ana', 'Martínez');INSERT INTO empleados@remote_db VALUES (104, 'Ana', 'Martínez');
-- Confirmar la transacción distribuidaCOMMIT;Gestión de errores en transacciones distribuidas
Section titled “Gestión de errores en transacciones distribuidas”-- Consultar transacciones distribuidas en dudaSELECT * FROM dba_2pc_pending;
-- Resolver manualmente una transacción en dudaCOMMIT FORCE 'transaction_id';-- oROLLBACK FORCE 'transaction_id';Mejores prácticas para transacciones
Section titled “Mejores prácticas para transacciones”-
Mantener transacciones cortas
- Las transacciones largas consumen más recursos y pueden causar bloqueos prolongados
- Divida las operaciones grandes en transacciones más pequeñas cuando sea posible
-
Confirmar o revertir explícitamente
- Siempre termine las transacciones con un COMMIT o ROLLBACK explícito
- Evite depender de los COMMIT o ROLLBACK implícitos
-
Usar savepoints estratégicamente
- Establezca savepoints antes de operaciones complejas o potencialmente problemáticas
- Use nombres descriptivos para los savepoints
-
Gestionar bloqueos adecuadamente
- Sea consciente de los bloqueos que generan sus transacciones
- Considere usar SELECT FOR UPDATE cuando sea necesario bloquear filas específicas
-
Manejar excepciones
- Implemente manejo de excepciones adecuado en bloques PL/SQL
- Realice ROLLBACK en caso de errores inesperados
Ejemplo de transacción bien estructurada en PL/SQL
Section titled “Ejemplo de transacción bien estructurada en PL/SQL”DECLARE v_error EXCEPTION; v_count NUMBER;BEGIN -- Iniciar transacción (implícito en PL/SQL)
-- Verificar condiciones previas SELECT COUNT(*) INTO v_count FROM clientes WHERE cliente_id = 1001; IF v_count = 0 THEN RAISE v_error; END IF;
-- Establecer savepoint SAVEPOINT sp_inicio;
-- Realizar operaciones INSERT INTO pedidos (pedido_id, cliente_id, total) VALUES (6001, 1001, 5000);
-- Establecer otro savepoint SAVEPOINT sp_despues_pedido;
-- Actualizar inventario UPDATE inventario SET cantidad = cantidad - 10 WHERE producto_id = 101; IF SQL%ROWCOUNT = 0 THEN ROLLBACK TO SAVEPOINT sp_despues_pedido; RAISE v_error; END IF;
-- Confirmar si todo está bien COMMIT; DBMS_OUTPUT.PUT_LINE('Transacción completada con éxito');
EXCEPTION WHEN v_error THEN ROLLBACK; DBMS_OUTPUT.PUT_LINE('Error en la transacción. Cambios revertidos.'); WHEN OTHERS THEN ROLLBACK; DBMS_OUTPUT.PUT_LINE('Error inesperado: ' || SQLERRM); RAISE;END;/