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.