Share via


Simultaneidade otimista

A simultaneidade otimista deriva seu nome da suposição otimista de que colisões entre transações raramente ocorrerão. Diz-se que uma colisão aconteceu quando outra transação atualiza ou exclui uma linha de dados entre o momento em que é lida pela transação atual e a hora em que é atualizada ou excluída. É o oposto da simultaneidade pessimista, ou bloqueio, em que o desenvolvedor de aplicativo acredita que essas colisões são comuns.

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

Para saber se uma linha foi alterada, sua nova versão é verificada em relação a uma versão em cache da linha. Essa verificação pode se basear na versão da linha, como a coluna de carimbo de data/hora no SQL Server ou nos 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 Com Commit de Leitura. O uso de um nível mais alto anula o aumento da simultaneidade obtida pelo uso de simultaneidade 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, ele executa uma instrução de atualização ou exclusão posicionada ou chama SQLSetPos exatamente como faria com a simultaneidade pessimista: o driver ou fonte de dados retornará SQLSTATE 01001 (conflito de operação do cursor) se a atualização ou exclusão falhar devido a uma colisão.

Se o próprio aplicativo implementar simultaneidade otimista, ele definirá o atributo de instrução SQL_ATTR_CONCURRENCY como SQL_CONCUR_READ_ONLY para ler uma linha. Se ele for comparar 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 dessa coluna.

O aplicativo atualiza ou exclui a linha aumentando a simultaneidade para SQL_CONCUR_LOCK (para obter acesso para gravação à linha) e executando uma instrução UPDATE ou DELETE com uma cláusula WHERE que especifica a versão ou os valores que a linha tinha quando o aplicativo a leu. Se a linha tiver mudado 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 exclusivamente as linhas, mas os valores de linha identificam exclusivamente as linhas apenas se incluem a chave primária.