Operações de gravação e de leitura/gravação
Você pode gerenciar o comportamento específico de operações simultâneas de gravação decidindo quando e como executar diferentes tipos de comandos. Os seguintes comandos são relevantes para esta discussão:
-
Comandos COPY, que executam carregamentos (iniciais ou incrementais)
-
Comandos INSERT que anexam uma ou mais linhas de cada vez
-
Comandos UPDATE, que modificam linhas existentes
-
Comandos DELETE, que removem linhas
As operações COPY e INSERT são operações de gravação pura, mas as operações DELETE e UPDATE são operações de leitura/gravação. (Para que as linhas sejam excluídas ou atualizadas, elas devem ser lidas primeiro.) Os resultados de operações simultâneas de gravação dependem dos comandos específicos que estão sendo executados simultaneamente. Operações COPY e INSERT na mesma tabela são mantidas em estado de espera até que o bloqueio seja liberado e, então, elas continuam normalmente.
Operações UPDATE e DELETE comportam-se de maneira diferente, pois elas dependem de uma leitura inicial da tabela antes de realizar qualquer gravação. Considerando que transações simultâneas são invisíveis entre si, operações de UPDATE e DELETE devem ler o snapshot dos dados da última confirmação. Quando a primeira operação UPDATE ou delete libera seu bloqueio, a segunda operação UPDATE ou DELETE precisa determinar se os dados com os quais ela vai trabalhar são potencialmente obsoletos. Eles não serão obsoletos, pois a segunda transação não obtém seu snapshot dos dados até depois que a primeira transação tenha liberado seu bloqueio.
Potencial situação de deadlock para transações simultâneas de gravação
Sempre que transações envolvem atualizações de mais que uma tabela, existe a possibilidade de que as transações em execução simultânea fiquem com deadlock quando ambas tentam gravar no mesmo conjunto de tabelas. Uma transação libera todos os seus bloqueios de tabela de uma só vez ao confirmar ou reverter; ela não libera os bloqueios um de cada vez.
Por exemplo, suponha que as transações T1 e T2 comecem aproximadamente ao mesmo tempo. Se T1 começa a gravar na tabela A e T2 tenta gravar na tabela B. ambas as transações podem continuar sem conflito; entretanto, se T1 conclui a gravação na tabela A e precisa começar a gravar na tabela B, ela não é capaz de continuar, pois T2 ainda mantém o bloqueio na tabela B. Por outro lado, se T2 conclui a gravação na tabela B e tenta gravar na tabela A, ela também não é capaz de continuar, pois T1 ainda mantém o bloqueio na tabela A. Como nenhuma das transações pode liberar seus bloqueios até a confirmação de todas as suas operações de gravação, nenhuma transação pode continuar.
Para evitar esse tipo de deadlock, você precisa programar operações simultâneas de gravação cuidadosamente. Por exemplo, você deve sempre atualizar as tabelas na mesma ordem nas transações e, se estiver especificando bloqueios, bloquear as tabelas na mesma ordem antes de executar qualquer operação DML.