Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

A atualização do SQL afetará sua subconsulta durante a execução da atualização?


** Editado **

Selecionando na tabela de destino

A partir de 13.2.9.8. Subconsultas na cláusula FROM:

As subconsultas na cláusula FROM podem retornar um escalar, coluna, linha ou tabela. As subconsultas na cláusula FROM não podem ser subconsultas correlacionadas, a menos que sejam usadas na cláusula ON de uma operação JOIN.

Então, sim, você pode realizar a consulta acima.

O problema

Há realmente dois problemas aqui. Há simultaneidade ou garantia de que ninguém mais altere os dados sob nossos pés. Isso é tratado com travamento. Lidar com a modificação real de valores novos versus antigos é tratado com tabelas derivadas.

Bloqueio

No caso de sua consulta acima, com o InnoDB, o MySQL executa o SELECT primeiro e adquire um bloqueio de leitura (compartilhado) em cada linha da tabela individualmente. Se você tivesse uma cláusula WHERE na instrução SELECT, somente os registros selecionados seriam bloqueados, onde os intervalos fariam com que quaisquer lacunas também fossem bloqueadas.

Um bloqueio de leitura impede que qualquer outra consulta adquira bloqueios de gravação, portanto, os registros não podem ser atualizados de outro lugar enquanto estiverem bloqueados para leitura.

Então, o MySQL adquire um bloqueio de gravação (exclusivo) em cada um dos registros da tabela individualmente. Se você tivesse uma cláusula WHERE em sua instrução UPDATE, apenas os registros específicos seriam bloqueados para gravação e, novamente, se a cláusula WHERE selecionasse um intervalo, você teria um intervalo bloqueado.

Qualquer registro que tivesse um bloqueio de leitura do SELECT anterior seria automaticamente escalado para um bloqueio de gravação.

Um bloqueio de gravação impede que outras consultas obtenham um bloqueio de leitura ou gravação.

Você pode usar o Innotop para ver isso executando-o no modo de bloqueio, iniciar uma transação, executar a consulta (mas não confirmá-la) e você verá os bloqueios no Innotop. Além disso, você pode visualizar os detalhes sem Innotop com SHOW ENGINE INNODB STATUS .

Impasses

Sua consulta estará vulnerável a um impasse se duas instâncias forem executadas ao mesmo tempo. Se a consulta A obtivesse bloqueios de leitura, a consulta B obtivesse bloqueios de leitura, a consulta A teria que esperar que os bloqueios de leitura da consulta B fossem liberados antes que pudesse adquirir os bloqueios de gravação. No entanto, a consulta B não liberará os bloqueios de leitura até que termine e não terminará a menos que possa adquirir bloqueios de gravação. A consulta A e a consulta B estão em um impasse e, portanto, em um impasse.

Portanto, você pode desejar executar um bloqueio de tabela explícito, tanto para evitar a grande quantidade de bloqueios de registro (que usa memória e afeta o desempenho) quanto para evitar um impasse.

Uma abordagem alternativa é usar SELECT ... FOR UPDATE em seu SELECT interno. Isso começa com bloqueios de gravação em todas as linhas, em vez de começar com leitura e escaloná-los.

Tabelas derivadas

Para o SELECT interno, o MySQL cria uma tabela temporária derivada. Uma tabela derivada é uma cópia real não indexada dos dados que residem na tabela temporária que é criada automaticamente pelo MySQL (em oposição a uma tabela temporária que você cria explicitamente e pode adicionar índices).

Como o MySQL usa uma tabela derivada, esse é o valor antigo temporário ao qual você se refere em sua pergunta. Em outras palavras, não há mágica aqui. O MySQL faz isso como você faria em qualquer outro lugar, com um valor temporário.

Você pode ver a tabela derivada fazendo um EXPLAIN em sua instrução UPDATE (suportada no MySQL 5.6+).