Dado um sistema que fornece:
- Controle / versão de concorrência otimista por objeto (usando o CAS - Check-and-Set)
- Transações que nunca precisam abranger mais do que um único objeto.
- Isolamento de instantâneo
Este sistema é considerado serializável ?
Em uma anomalia de inclinação de gravação, duas transações (T1 e T2) lêem simultaneamente um conjunto de dados sobrepostos (por exemplo, valores V1 e V2), fazem atualizações simultâneas (por exemplo, atualizações T1 V1, T2 atualizam V2) e finalmente confirmam simultaneamente, sem ter visto a atualização realizada pelo outro. Se o sistema fosse serializável, essa anomalia seria impossível, pois T1 ou T2 teria que ocorrer "primeiro" e ser visível para o outro. Por outro lado, o isolamento de instantâneo permite anomalias de inclinação de gravação.
Como um exemplo concreto, imagine V1 e V2 são dois saldos mantidos por uma única pessoa, Phil. O banco permitirá que V1 ou V2 corra um déficit, desde que o total mantido em ambos nunca seja negativo (ou seja, V1 + V2 ≥ 0). Atualmente, ambos os saldos são de US $ 100. Phil inicia duas transações simultaneamente, T1 retirando US $ 200 da V1 e T2 retirando US $ 200 da V2.
Com base nisso, parece que ter o potencial de distorção de gravação é a única razão para um sistema que garante que o isolamento de captura instantânea não seja serializável.
No entanto, em um sistema que não permite que uma transação abranja vários objetos (no exemplo acima V1 e V2), parece impossível ocorrer inclinação da gravação .
Portanto, o sistema descrito acima é serializável. Isso está correto?
fonte
Respostas:
Não, não acho que suas estipulações resultem em um sistema que devemos considerar serializável.
O isolamento de instantâneo é uma técnica que garante que uma transação veja o mesmo conjunto de dados em toda a transação. O isolamento de instantâneo fornece algumas garantias, mas não define todas as características necessárias para entender como as transações realmente funcionam (a menos que optemos por combinar o isolamento de instantâneo e o MVCC).
O isolamento de instantâneo é mais comumente implementado usando o MVCC, Multi Version Consistency Control. O MVCC define mais detalhes das transações no contexto de seus instantâneos: diz-se que eles requerem isolamento somente quando gravam conflitos (somente locais ou locais + valores, dependendo da implementação). O MVCC fornece um modelo de consistência relaxado e sofre distorção de gravação.
Os modelos de consistência relaxada são difíceis de entender porque são como um híbrido entre nenhum isolamento e isolamento total.
Então, vamos começar primeiro com um modelo de concorrência estrito. Duas transações devem ser isoladas uma da outra se uma gravar em qualquer dado que a outra leia ou grave (e vice-versa ...).
Quando não sabemos por que uma transação lê dados, devemos presumir que uma leitura de valor diferente pode alterar o comportamento do cliente envolvido, e é por isso que a condição de transações sobrepostas indica isolamento. Sem isolamento, uma leitura de dados antigos em um instantâneo pode exibir facilmente consistência relaxada, outro termo para o qual é inconsistência, ou seja, erro.
Precisamos considerar apenas os dados exatos lidos ou gravados pelas transações; quaisquer dados fora desse conjunto não precisam ser considerados. No entanto, é fundamental perceber que, quando estamos falando de dados lidos por uma transação, necessariamente devemos incluir todos e quaisquer "metadados" (e dados e metadados lidos por meta operações, como verificação de restrições). Exemplos de metadados são / meta operações são: identificação de uma nova chave primária única; outra é a soma de uma coluna inteira; outra é procurar algo e não encontrá-lo; pesquisas ou somas. Isso vai para o comentário de @ Matthew sobre a prevenção de duplicatas, bem como para a resposta @Tersosauros, na qual ele considera estado.
Por exemplo, isso significa que duas transações se sobrepõem (requerem isolamento) quando ambas inserem uma linha (assumindo uma restrição de chave primária exclusiva) porque verificar a restrição de chave é sinônimo de ler toda a coluna da chave primária. Como outro exemplo, procurar algo e encontrá-lo é como ler esse valor, no entanto, não encontrá-lo é como olhar para todos os valores da coluna.
O MVCC protege apenas contra gravações sobrepostas ou conflitantes, mas não protege contra leituras (a menos que também seja gravado por essa transação). Portanto, para obter um erro de consistência no MVCC, tudo o que precisamos fazer é ler algo que é alterado por outra transação (onde a outra transação acontece depois que o instantâneo do anterior é obtido, mas confirma primeiro), enquanto a outra transação continua usando dados obsoletos e toma qualquer decisão de maneira diferente com base nesses dados obsoletos, em comparação com o que teria feito com dados atualizados. É mais fácil causar do que você imagina.
A consistência relaxada é outra maneira de dizer potencialmente inconsistente ou propenso a erros. (A consistência relaxada não deve ser confundida com a consistência eventual, que é outra forma popular de erro propensa a "NoSQL".)
Na sua pergunta, quando você diz que as transações nunca precisam abranger mais de um objeto, isso deve se aplicar às leituras e gravações e aos metadados (e operações meta), incluindo verificação de consistência, agregados de colunas inteiras, verificações de ausência, pesquisas de intervalo etc. .: se sim, então até agora tudo bem.
Contudo...
Suponho que você esteja usando o isolamento de snapshot (MVCC) em objetos individuais (digamos, em vez de bloqueio de objeto). (Você também menciona o CAS; já ouvi falar de comparar e trocar e, testar e configurar, mas não verificar e configurar, embora eu assuma que seja semelhante).
Sua pergunta escrita sugere que "objetos" têm mais de um campo; caso contrário, as estipulações da pergunta seriam desnecessárias.
Portanto, como os objetos manipulados por snapshots / MVCC têm mais de um campo, é mais provável que você incline a inclinação em objetos únicos. Se duas transações atualizarem o mesmo objeto ao mesmo tempo, pode-se ler um campo do valor do objeto tornado obsoleto por uma outra transação simultânea no mesmo objeto e continuar sem saber, portanto, inconsistência potencial (também conhecida como erro).
Em vez disso, você poderia usar o bloqueio de objetos, o que impediria duas transações (para atualização) de olharem para o mesmo objeto se outra transação já estivesse em andamento.
Acredito que uma forma alternativa de isolamento de instantâneo possa ser feita sem o uso do modelo de comparação de conjunto de gravação quebrado do MVCC. Portanto, você pode (algoritmicamente) promover o conjunto de comparação de somente gravação para incluir também o conjunto de leitura. Em seguida, duas transações atualizando o mesmo objeto não seriam capazes de causar distorção de gravação (porque a que tentar confirmar posteriormente seria abortada). Eu acho que essa pode ser a solução apropriada para o problema que você está descrevendo, porque você já está obtendo a maior parte do benefício que o MVCC nos compraria, impedindo transações com vários objetos.
(Precisamos considerar apenas os itens / campos exatos e específicos lidos ou gravados, mas devemos incluir aqueles lidos como metadados, potencialmente durante as operações meta para impedir a inclinação da gravação (ou seja, erro). Se removermos o conjunto de leitura do conjunto de comparação , ou se não considerarmos os metadados (potencialmente usados por meta-operações), teremos um modelo que permitirá erros.
fonte
Eu acho que, como @ pjc50 afirmou, (ênfase adicionada :) " se as transações forem limitadas à leitura / gravação de um único objeto", "a resposta é sim". No entanto, acho que onde isso ocorre é na idéia de um único objeto.
No exemplo retirado do isolamento de instantâneo , T1 e T2 não compartilham nenhum valor. No entanto, eles ainda são um potencial de distorção de gravação porque " nenhum [viu] a atualização realizada pela outra " fonte . Portanto, é a capacidade de uma transação ver todas as outras atualizações antes da confirmação que torna uma transação verdadeiramente serializável.
Da serialização :
Infelizmente, por causa disso (e como aponta @Matthew Mark Miller ), também devemos considerar o estado e os valores. Com essa consideração, duas transações usando o OCC teriam o potencial de distorção de gravação sempre que qualquer estado do banco de dados fosse gravado .
fonte