Compartilhar via


Concorrência otimista

A simultaneidade otimista deriva seu nome da suposição otimista de que raramente ocorrerão colisões entre transações; diz-se que ocorreu uma colisão quando outra transação atualiza ou exclui uma linha de dados entre a hora em que é lida pela transação atual e a hora em que ela é atualizada ou excluída. É o oposto da concorrência pessimista, ou bloqueio, em que o desenvolvedor de aplicativos acredita que tais colisões são comuns.

Na simultaneidade otimista, uma linha é deixada desbloqueada até chegar a hora de atualizá-la ou excluí-la. Nesse ponto, a linha é relida e verificada para ver se ela foi alterada desde a última leitura. Se a linha tiver sido alterada, a atualização ou exclusão falhará e deverá ser tentada novamente.

Para determinar se uma linha foi alterada, sua nova versão é verificada em uma versão armazenada em cache da linha. Essa verificação pode ser baseada na versão da linha, como a coluna de carimbo de data/hora no SQL Server ou os valores de cada coluna na linha. Muitos DBMSs não dão suporte a versões de linha.

A simultaneidade otimista pode ser implementada pela fonte de dados ou pelo aplicativo. Em ambos os casos, o aplicativo deve usar um nível baixo de isolamento de transação, como "Read Committed"; utilizar um nível mais alto anula o aumento da simultaneidade obtida com o uso de concorrência otimista.

Se a simultaneidade otimista for implementada pela fonte de dados, o aplicativo definirá o atributo de instrução SQL_ATTR_CONCURRENCY como SQL_CONCUR_ROWVER ou SQL_CONCUR_VALUES. Para atualizar ou excluir uma linha, o sistema executa um comando de atualização ou exclusão posicionado ou chama SQLSetPos da mesma forma que faria com concorrência pessimista; o driver ou a fonte de dados retornará SQLSTATE 01001 (conflito de operação de cursor) se a atualização ou exclusão falhar devido a um conflito.

Se o próprio aplicativo implementar concorrência otimista, ele definirá o atributo de instrução SQL_ATTR_CONCURRENCY como SQL_CONCUR_READ_ONLY para ler uma linha. Se a aplicação comparar as versões de linha e não souber a coluna de versão da linha, chamará SQLSpecialColumns com a opção SQL_ROWVER para determinar o nome desta coluna.

O aplicativo atualiza ou exclui a linha aumentando o nível de simultaneidade para SQL_CONCUR_LOCK (para obter acesso de gravação à linha) e executa uma instrução UPDATE ou DELETE com uma cláusula WHERE que especifica a versão ou os valores que a linha possuía quando o aplicativo a leu. Se a linha tiver sido alterada desde então, a instrução falhará. Se a cláusula WHERE não identificar exclusivamente a linha, a instrução também poderá atualizar ou excluir outras linhas; As versões de linha sempre identificam linhas exclusivamente, mas os valores de linha identificam exclusivamente as linhas somente se elas incluem a chave primária.