Oracle SQL: Bloqueo de filas en la instrucción select

El objetivo de esta publicación es explicar cómo bloquear un registro en una base de datos Oracle mediante una instrucción select.

Introducción

El objetivo de esta publicación es explicar cómo bloquear un registro en una base de datos Oracle, utilizando una instrucción select. Esto nos permite bloquear un registro sin necesidad de cambiarlo.

Aunque esto puede no parecer un caso de uso muy común, la verdad es que podemos necesitarlo para programas más complejos (implementados, por ejemplo, en PL/SQL), donde necesitamos hacer algunas validaciones complejas antes de decidir actualizar un registro determinado, y necesitamos mantenerlo bloqueado durante esas validaciones, para que ninguna otra transacción pueda modificarlo simultáneamente.

Usaremos SQL Developer para interactuar con la base de datos y realizar las consultas para este tutorial.

Bloqueando el mismo registro

Como de costumbre, comenzaremos creando una tabla ficticia simple, para mantener nuestros datos. Compruebe el siguiente ejemplo de creación.

create table Worker(WorkerID varchar(20),WorkerName varchar(255),WorkerJob varchar(255),CONSTRAINT PK_Worker PRIMARY KEY (WorkerID));

Después de eso, insertaremos algunos registros ficticios, para que tengamos datos en los que trabajar. Insertaremos tres registros y luego confirmaremos la transacción. Puede usar el botón confirmar en el menú Desarrollador SQL o confirmar explícitamente la transacción con una instrucción SQL.

insert into worker values ('1','John', 'nurse');insert into worker values ('2','Grace', 'farmer');insert into worker values ('3','Smith', 'doctor');

Ahora abriremos una nueva hoja de trabajo no compartida, para que podamos probar las instrucciones SQL en transacciones independientes. Consulte la figura 1 sobre cómo hacerlo. Puede leer más sobre las hojas de trabajo no compartidas de SQL Developer en esta publicación anterior.

 Hoja de trabajo no compartida del desarrollador SQL

Figura 1: Apertura de una nueva hoja de trabajo no compartida.

Ahora, lo primero que vamos a hacer es ejecutar una selección regular en ambas hojas de trabajo. Haremos una selección para obtener el registro donde el WorkerID es igual a 1. No realice confirmaciones ni reversiones, simplemente ejecute la misma consulta en ambas hojas de trabajo.

select * from worker where WorkerID = 1;

Como era de esperar, no hay problema con la concurrencia y recibiremos el registro en ambas transacciones (con el nombre de trabajo igual a «John»).

Ahora, regresaremos a la primera hoja de trabajo (la misma donde creamos la tabla) y agregaremos una cláusula «for update» al final de la instrucción select, como se indica a continuación. De nuevo, no hagas ninguna confirmación o reversión.

select * from worker where WorkerID = 1 for update;

Cuando hacemos esto, estamos bloqueando los registros del conjunto de resultados, sin la necesidad de actualizarlos . En otras palabras, estamos bloqueando explícitamente los registros. Por supuesto que una vez que los tengamos bloqueados, podemos actualizarlos si queremos. Los bloqueos en los registros se liberan cuando hacemos la próxima confirmación o reversión .

Por lo tanto, para probar si los bloqueos funcionan, ahora vamos a la segunda hoja de trabajo (la hoja de trabajo no compartida que abrimos). Allí, si hacemos una selección regular, sin la frase «para actualizar», obtendremos el registro sin ningún problema.

select * from worker where WorkerID = 1;

Pero luego, si repetimos el select, ahora con la oración «for update» al final, se colgará, ya que otra transacción tiene el registro con WorkerID igual a 1 bloqueado, y estamos tratando de bloquearlo nuevamente.

select * from worker where WorkerID = 1 for update;

Para desbloquearlo, simplemente regrese a la primera hoja de trabajo y confirme o revierta la transacción. Ahora, vuelva a la hoja de trabajo no compartida y la instrucción SQL debería haberse ejecutado, devolviendo el registro deseado.

Bloquear diferentes registros

Una cosa importante a tener en cuenta es que solo los registros que forman parte del conjunto de resultados están bloqueados por la transacción. Por lo tanto, diferentes transacciones pueden hacer «seleccionar para actualizar» en diferentes registros.

Para probar esto, vaya a la primera hoja de trabajo y seleccione grabar 1 y 3, con la siguiente oración de selección:

select * from worker where WorkerID = 1 or WorkerID = 3 for update;

Ahora vaya a la hoja de trabajo no compartida e intente bloquear el registro 2.

select * from worker where WorkerID = 2 for update;

Debería funcionar y devolver un resultado, ya que el registro con ID de trabajo igual a 2 no fue bloqueado por la primera transacción. Ahora, si en la misma hoja de trabajo no compartida intentamos bloquear el registro con ID de trabajador igual a 1 o el registro con ID de trabajador igual a 3 (o ambos), se colgará hasta que confirmemos o revertamos la transacción de la primera hoja de trabajo.

Contenido relacionado

  • Selección de Oracle para estado de actualización

Write a Comment

Tu dirección de correo electrónico no será publicada.