La administración de la concurrencia de datos en Oracle 19c es fundamental para mantener la integridad y el rendimiento de las transacciones en entornos multiusuario.
Oracle utiliza una combinación de técnicas y tecnologías para manejar la concurrencia, garantizando que múltiples usuarios o aplicaciones puedan acceder y modificar los datos simultáneamente sin provocar conflictos o inconsistencias.
A continuación, se describen las principales estrategias y conceptos utilizados para gestionar la concurrencia en Oracle 19c.
1. Modelo de Consistencia Multiversión (MVCC)
Oracle utiliza un enfoque de Consistencia Multiversión para permitir que múltiples transacciones lean y escriban datos de manera simultánea. Con MVCC:
- Lecturas Consistentes: Cada transacción ve una instantánea de los datos en el momento exacto en que comenzó, asegurando así que no interferirá con otras transacciones en curso. Este mecanismo es esencial para mantener la integridad de los datos, ya que las lecturas no bloquean las escrituras, permitiendo un flujo constante de información, y viceversa, lo que asegura que todas las operaciones se realicen de manera eficiente y sin conflictos.
- Undo Data: El uso de undo permite que las transacciones lean versiones anteriores de los datos, proporcionando una vista coherente aunque otras transacciones realicen cambios.
2. Bloqueos y Gestión de Recursos
- Bloqueos de Filas y Tabla: Oracle utiliza bloqueos a nivel de fila (row-level locks) y bloqueos a nivel de tabla (table-level locks) para controlar el acceso concurrente. Los bloqueos a nivel de fila son preferibles porque permiten que múltiples transacciones accedan a diferentes filas en la misma tabla simultáneamente sin interferir entre sí.
- Bloqueos Implícitos y Explícitos: Oracle maneja automáticamente bloqueos (implícitos) durante las operaciones de escritura. Sin embargo, los usuarios también pueden establecer bloqueos explícitos si es necesario usando la instrucción
SELECT ... FOR UPDATE.
3. Niveles de Aislamiento de Transacciones
El nivel de aislamiento de transacciones determina cómo se gestionan los cambios en una base de datos. Oracle soporta varios niveles de aislamiento:
- Read Committed: Es el nivel de aislamiento por defecto. Permite que una transacción vea solo los cambios confirmados por otras transacciones. Esto evita problemas de lecturas sucias.
- Serializable: Proporciona un nivel de aislamiento más estricto, donde una transacción se comporta como si se hubiera ejecutado en un entorno completamente aislado de otras transacciones. Esto puede causar bloqueos y esperas, pero garantiza resultados consistentes.
- Read Uncommitted: Permite lecturas de datos no confirmados (no se aplica de forma estricta en Oracle).
4. Gestión del Tiempo de Espera y Deadlocks
- Time-Outs de Espera: Oracle permite definir tiempos de espera para bloqueos, lo que ayuda a evitar que las transacciones se queden colgadas indefinidamente. Si una transacción no puede obtener un bloqueo dentro del tiempo especificado, se produce un error.
- Detección y Resolución de Deadlocks: Oracle tiene un mecanismo para detectar deadlocks (bloqueos mutuos) automáticamente. Cuando detecta un deadlock, Oracle finaliza una de las transacciones involucradas para liberar los recursos y permitir que las demás continúen.
5. Optimización y Diseño de Aplicaciones
- Diseño de Consultas Eficientes: Es esencial escribir consultas que minimicen el tiempo durante el cual una transacción mantiene bloqueos. Esto puede implicar el uso de índices y la optimización de la lógica de negocios.
- Uso de Tablas Temporales: Para operaciones complejas o de informes que no requieren datos persistentes, el uso de tablas temporales puede ayudar a reducir el contencioso en tablas principales.
6. Particionamiento de Tablas
El particionamiento de tablas puede ser útil para mejorar la concurrencia. Al segmentar grandes tablas en particiones más pequeñas, las operaciones sobre diferentes particiones pueden realizarse en paralelo, reduciendo bloqueos y mejorando el rendimiento.
7. Recuperación y Replicación
- Oracle Data Guard y Active Data Guard: Para garantizar la disponibilidad y la recuperación, Oracle ofrece tecnologías de replicación que pueden mantener instancias secundarias actualizadas y que pueden también ser utilizadas para operaciones de lectura, aliviando la carga de la base de datos principal.
8. Uso de Oracle RAC (Real Application Clusters)
Oracle RAC permite la escalabilidad y la alta disponibilidad mediante la ejecución de bases de datos en múltiples nodos. Esto facilita el manejo de la concurrencia al permitir que múltiples instancias trabajen con la misma base de datos, asegurando el acceso simultáneo con mecanismos de coordinación adecuados.
Práctica Sencilla
Aquí tienes una práctica sencilla para demostrar el manejo de concurrencia en Oracle 19c. Esta práctica incluirá crear un entorno de prueba utilizando tablas y transacciones que simulan una situación de concurrencia. El ejemplo se centrará en el uso de bloqueos, niveles de aislamiento de transacciones y se observarán situaciones de espera y potenciales deadlocks.
Objetivos
- Crear una tabla para simular un entorno de concurrencia.
- Realizar transacciones en paralelo para ver cómo maneja Oracle los bloqueos.
- Observar el comportamiento de los niveles de aislamiento.
Requerimientos
- Tener acceso a una base de datos Oracle 19c.
- Usar herramientas como SQL*Plus, SQL Developer o cualquier cliente SQL que prefieras.
Paso 1: Preparar el Entorno
Primero, abre tu entorno de SQL y ejecuta el siguiente código para crear una tabla de ejemplo
Crear una tabla sencilla de cuentas bancarias
CREATE TABLE cuentas_bancarias (
id NUMBER PRIMARY KEY,
saldo NUMBER
);
Insertar algunos datos
INSERT INTO cuentas_bancarias (id, saldo) VALUES (1, 1000);
INSERT INTO cuentas_bancarias (id, saldo) VALUES (2, 2000);
INSERT INTO cuentas_bancarias (id, saldo) VALUES (3, 3000);
COMMIT;
Paso 2: Simular Transacciones Concurridas
- Abrir dos sesiones en tu cliente SQL (puedes usar dos ventanas de SQL Developer o dos conexiones en SQL*Plus).
- En la Sesión 1, ejecuta la siguiente transacción:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
DECLARE
v_saldo NUMBER;
BEGIN
-- Bloqueo de la fila de la cuenta con ID 1
SELECT saldo INTO v_saldo FROM cuentas_bancarias WHERE id = 1 FOR UPDATE;
-- Simula algún procesamiento (espera de 10 segundos)
DBMS_LOCK.SLEEP(10);
-- Modificar el saldo
UPDATE cuentas_bancarias SET saldo = v_saldo + 500 WHERE id = 1;
COMMIT;
END;
/
3. En la Sesión 2, ejecuta la siguiente transacción casi al mismo tiempo:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
DECLARE
v_saldo NUMBER;
BEGIN
-- Intentando bloquear la fila de la cuenta con ID 1
SELECT saldo INTO v_saldo FROM cuentas_bancarias WHERE id = 1 FOR UPDATE;
-- Simula algún procesamiento (espera de 5 segundos)
DBMS_LOCK.SLEEP(5);
-- Modificar el saldo
UPDATE cuentas_bancarias SET saldo = v_saldo - 300 WHERE id = 1;
COMMIT;
END;
/
Paso 3: Observar el Comportamiento
- En la Sesión 1: Cuando ejecutes esta transacción, se producirá un bloqueo de la fila con id = 1 y el procesamiento se detendrá por 10 segundos.
- En la Sesión 2: Como esta sesión también está intentando bloquear la misma fila, se quedará esperando hasta que la Sesión 1 complete su transacción. Después de 10 segundos, la Sesión 1 hará commit y la Sesión 2 podrá continuar. Esto ilustra cómo Oracle maneja concurrencia y bloqueos.
Paso 4: Prueba de Niveles de Aislamiento
Para experimentar con diferentes niveles de aislamiento:
- Modifica la sesión y prueba el nivel SERIALIZABLE en vez de READ COMMITTED.
Cambiar la línea de aislamiento en la sesión 1 y la sesión 2 a SERIALIZABLE
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Esto generará errores si dos transacciones intentan acceder a los mismos datos simultáneamente, ilustrando cuán estrictos son los niveles de aislamiento.
Paso 5: Prueba de Deadlock (Opcional)
Para provocar un deadlock, puedes modificar tus sesiones para que cada una intente bloquear un recurso que la otra necesita.
- Cambia la lógica de la Sesión 1 para bloquear la fila con
id = 2. - En la Sesión 2, bloquea la fila con
id = 1antes de acceder aid = 2.
Asegúrate de que ambas sesiones ejecuten un bloque de código similar al siguiente para observar cómo el sistema detecta un deadlock:
En la Sesión 1
LOCK TABLE cuentas_bancarias IN EXCLUSIVE MODE;
Inicia la transacción
UPDATE cuentas_bancarias SET saldo = saldo - 100 WHERE id = 2;
En la Sesión 2
LOCK TABLE cuentas_bancarias IN EXCLUSIVE MODE;
Inicia la transacción
UPDATE cuentas_bancarias SET saldo = saldo - 100 WHERE id = 1;
Al finalizar estas pruebas, habrás observado cómo Oracle maneja la concurrencia de datos a través de bloqueos, niveles de aislamiento y cómo se generan y resuelven posibles deadlocks.
Si tienes preguntas específicas sobre el proceso o alguna parte de la práctica, ¡pregunta sin dudar!






Deja un comentario