sql >> Base de Datos >  >> RDS >> Oracle

¿La actualización de SQL afectará su subconsulta durante la ejecución de la actualización?

** Editado **

Selección de la tabla de destino

Desde 13.2.9.8. Subconsultas en la Cláusula FROM:

Las subconsultas en la cláusula FROM pueden devolver un escalar, una columna, una fila o una tabla. Las subconsultas en la cláusula FROM no pueden ser subconsultas correlacionadas, a menos que se usen dentro de la cláusula ON de una operación JOIN.

Entonces, sí, puede realizar la consulta anterior.

El problema

Realmente hay dos problemas aquí. Hay concurrencia, o garantizar que nadie más cambie los datos que tenemos bajo nuestros pies. Esto se maneja con bloqueo. El tratamiento de la modificación real de los valores nuevos frente a los antiguos se maneja con tablas derivadas.

Bloqueo

En el caso de su consulta anterior, con InnoDB, MySQL realiza SELECCIONAR primero y adquiere un bloqueo de lectura (compartido) en cada fila de la tabla individualmente. Si tuviera una cláusula WHERE en la instrucción SELECT, solo se bloquearían los registros que seleccione, mientras que los rangos también bloquearían cualquier espacio en blanco.

Un bloqueo de lectura evita que cualquier otra consulta adquiera bloqueos de escritura, por lo que los registros no se pueden actualizar desde ningún otro lugar mientras están bloqueados para lectura.

Luego, MySQL adquiere un bloqueo de escritura (exclusivo) en cada uno de los registros de la tabla individualmente. Si tuviera una cláusula WHERE en su instrucción UPDATE, entonces solo los registros específicos estarían bloqueados contra escritura y nuevamente, si la cláusula WHERE seleccionaba un rango, entonces tendría un rango bloqueado.

Cualquier registro que tuviera un bloqueo de lectura del SELECT anterior se escalaría automáticamente a un bloqueo de escritura.

Un bloqueo de escritura evita que otras consultas obtengan un bloqueo de lectura o escritura.

Puede usar Innotop para ver esto ejecutándolo en modo de bloqueo, inicie una transacción, ejecute la consulta (pero no la confirme) y verá los bloqueos en Innotop. Además, puede ver los detalles sin Innotop con SHOW ENGINE INNODB STATUS .

Interbloqueos

Su consulta es vulnerable a un interbloqueo si se ejecutaron dos instancias al mismo tiempo. Si la consulta A obtuvo bloqueos de lectura, luego la consulta B obtuvo bloqueos de lectura, la consulta A tendría que esperar a que se liberaran los bloqueos de lectura de la consulta B antes de poder adquirir los bloqueos de escritura. Sin embargo, la consulta B no liberará los bloqueos de lectura hasta que finalice y no finalizará a menos que pueda adquirir bloqueos de escritura. La consulta A y la consulta B están en un punto muerto y, por lo tanto, en un punto muerto.

Por lo tanto, es posible que desee realizar un bloqueo de tabla explícito, tanto para evitar la gran cantidad de bloqueos de registros (que usan memoria y afecta el rendimiento) como para evitar un interbloqueo.

Un enfoque alternativo es usar SELECCIONAR ... PARA ACTUALIZAR en su SELECCIÓN interna. Esto comienza con bloqueos de escritura en todas las filas en lugar de comenzar con lectura y escalarlos.

Tablas derivadas

Para el SELECT interno, MySQL crea una tabla temporal derivada. Una tabla derivada es una copia real no indexada de los datos que viven en la tabla temporal que MySQL crea automáticamente (a diferencia de una tabla temporal que usted crea explícitamente y a la que puede agregar índices).

Dado que MySQL usa una tabla derivada, ese es el valor anterior temporal al que se refiere en su pregunta. En otras palabras, aquí no hay magia. MySQL lo hace como lo haría en cualquier otro lugar, con un valor temporal.

Puede ver la tabla derivada haciendo un EXPLAIN contra su instrucción UPDATE (compatible con MySQL 5.6+).