2012-03-04 10 views
7

En la declaración de actualización de Oracle SQL, suponiendo que la actualización afectaría a 5 filas, ¿la instrucción de actualización actualiza las 5 filas de forma concurrente o secuencial? P.ej.En la declaración de actualización de Oracle SQL, ¿la actualización de filas ocurre al mismo tiempo?

UPDATE table1 
set column2 = 'completed' WHERE 
index between 1 AND 5 

En la declaración anterior, habría índice de 1 a 5 se actualizará en secuencia, es decir, 1, 2, 3, 4 a continuación, 5, o sería ocurrir simultáneamente (1-5 todos a la vez).

Me he referido a Oracle documentation pero parece que no se menciona nada al respecto.

+0

Lógicamente, se realizan simultáneamente. En la práctica, no lo hacen, pero no podrás ver la diferencia. Se vuelve más interesante si lo hace 'ACTUALIZAR Tabla1 SET Index = Índice + 1 WHERE Índice ENTRE 1 Y 5'. –

Respuesta

4

Después de que se haya ejecutado la instrucción UPDATE, los efectos de la declaración serán visibles para el resto de la transacción (y si se confirma, para otras transacciones). ¿En qué orden Oracle lo hará físicamente, es un implementación detalle (de manera similar cómo el orden del resultado SELECT no está garantizado a menos que especifique ORDER BY).


En la mayoría de los casos, este pedido no le importa al cliente. Un caso donde podría ser es evitar interbloqueos con otra transacción que está actualizando el conjunto de filas superpuestas. ACTUALIZAR bloqueará la fila que se está actualizando hasta el final de la transacción, por lo que si dos transacciones intentan bloquear las mismas filas, pero en orden diferente, puede producirse un punto muerto.

La forma estándar de evitar interbloqueos es bloquear siempre en un orden bien definido. Por desgracia, UPDATE no tiene la cláusula ORDER BY, pero se puede hacer esto:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
SELECT ... WHERE condition ORDER BY ... FOR UPDATE; 
UPDATE ... WHERE condition; 
COMMIT; 

Dónde condition es igual para ambos estados. El nivel de aislamiento serializable es necesario para WHERE para ver siempre el mismo conjunto de filas en ambas sentencias.

O, en PL/SQL se podría hacer algo como esto:

DECLARE 
    CURSOR CUR IS SELECT * FROM YOUR_TABLE WHERE condition ORDER BY ... FOR UPDATE; 
BEGIN 
    FOR LOCKED_ROW IN CUR LOOP 
     UPDATE YOUR_TABLE SET ... WHERE CURRENT OF CUR; 
    END LOOP; 
END; 
/
2

El enlace que proporcionó en realidad lo cubre. Oracle siempre impone la coherencia de lectura a nivel de declaración: esto significa que ninguna consulta en la tabla 1 devolverá algunos registros actualizados y otros no. Será todo o nada e independientemente del nivel de aislamiento.

+0

Gracias. Solo para aclarar más, suponiendo que el índice 4 tiene un bloqueo de lectura, ¿la instrucción de actualización esperará a que se levante el bloqueo de lectura para actualizar las 5 filas? – Ted

+0

@Ted: en Oracle, los lectores y escritores no se bloquean entre sí. Cuando se actualizan los datos, los datos antiguos se guardan automáticamente por un tiempo (UNDO). Esto permite que las consultas lean datos en un punto en el tiempo, independientemente de cualquier cambio que esté ocurriendo. –

+0

@jonearles Sí, pero los escritores ** do ** se bloquean entre sí (cuando están escribiendo en las mismas filas). Los escritores bloquearán fila por fila, lo que significa que existe la posibilidad de un punto muerto si las escrituras no se realizan en el mismo orden en todas las transacciones. Como UPDATE no tiene la cláusula ORDER BY, se debe usar un 'SELECT ... ORDER BY ... FOR UPDATE' por separado para garantizar la orden de bloqueo. –

4

Potencialmente cualquiera.

En este caso, ya que solo está actualizando 5 filas, sería muy poco probable que el DML paralelo sea apropiado. Suponiendo que el UPDATE no invoca el DML paralelo, las filas se actualizarán secuencialmente aunque el orden en el que se actualizan las filas es arbitrario. INDEX 1 podría ser el primero en actualizarse, el último en actualizarse, o podría actualizarse en el medio. Depende del plan de consulta.

2

ACTUALIZAR, ELIMINAR e INSERTAR no tienen una orden definida. Conceptualmente se aplican a un conjunto y se hacen todos a la vez. En términos prácticos, no confíe en ninguna secuencia que pueda observar: es un detalle de implementación que puede cambiar, y solo sucede porque el mundo real se interpone en el camino de la teoría.

+0

¡Gracias! Debo inferir que la actualización se realiza sobre una base de conjunto, es decir, la actualización esperará a que todas las filas estén disponibles antes de realizar la declaración de actualización. – Ted

+0

@Ted: Oracle bloquea el bloqueo de nivel, pero no es necesario desbloquear todas las filas cuando se inicia la actualización. – jmoreno

0

Todos los registros se actualizarán como un solo registro en una transacción. Oracle no garantiza ningún orden en la secuencia de actualización.

Puede actualizar cualquier campo por valor de dbms_transaction.local_transaction_id en su tabla para verificarlo.

Cuestiones relacionadas