No, non credo che le tue disposizioni risultino in un sistema che dovremmo considerare serializzabile.
L'isolamento dello snapshot è una tecnica che garantisce che una transazione veda lo stesso set di dati nell'intera transazione. L'isolamento dello snapshot fornisce alcune garanzie, ma non definisce tutte le caratteristiche necessarie per capire come funzionano veramente le transazioni (a meno che non scegliamo di confondere l'isolamento dello snapshot e MVCC).
L'isolamento dello snapshot è più comunemente implementato usando MVCC, Multi Version Coistency Control. MVCC definisce più dettagli delle transazioni nel contesto delle loro istantanee: si dice che richiedono l'isolamento solo quando si scrive un conflitto (solo posizioni, o posizioni + valori, a seconda dell'implementazione). MVCC fornisce un modello di coerenza rilassato e soffre di inclinazione di scrittura.
I modelli di coerenza rilassata sono difficili da capire perché sono come un ibrido tra nessun isolamento e completo isolamento.
Quindi, iniziamo con un rigoroso modello di concorrenza prima. Due transazioni devono essere isolate l'una dall'altra se una scrive su dati che l'altra legge o scrive (e viceversa ...).
Quando non sappiamo perché una transazione legge i dati, dobbiamo presumere che un valore diverso possa alterare il comportamento del cliente coinvolto, motivo per cui la condizione di transazioni sovrapposte indica l'isolamento. Senza isolamento, una lettura di dati non aggiornati in un'istantanea può facilmente mostrare una coerenza rilassata, un altro termine per il quale è incoerenza, vale a dire errore.
Dobbiamo solo considerare i dati esatti letti o scritti dalle transazioni, non è necessario prendere in considerazione tutti i dati al di fuori di quel set. Tuttavia, è fondamentale rendersi conto che quando stiamo parlando di dati letti da una transazione, dobbiamo necessariamente includere tutti i dati "meta" (e dati e metadati letti da meta operazioni come il controllo dei vincoli). Esempi di metadati sono / meta operazioni sono: identificazione di una nuova chiave primaria unica; un altro è la somma di un'intera colonna; un altro è cercare qualcosa e non trovarlo; intervallo di ricerche o somme. Questo va al commento di @ Matthew sulla prevenzione dei duplicati, così come la risposta di @Tersosauros, in cui considera lo stato.
Ad esempio, ciò significa che due transazioni si sovrappongono (richiedono l'isolamento) quando entrambe inseriscono una riga (presupponendo un vincolo di chiave primaria univoco) poiché il controllo del vincolo di chiave è sinonimo di lettura dell'intera colonna di chiave primaria. Come altro esempio, cercare qualcosa e trovarlo è come leggere quel valore, tuttavia, non trovarlo è come guardare ogni valore nella colonna.
MVCC protegge solo da scritture sovrapposte o in conflitto, ma non protegge dalle letture (a meno che non siano scritte anche da quella transazione). Pertanto, per ottenere un errore di coerenza in MVCC, tutto ciò che dobbiamo fare è leggere qualcosa che viene modificato da un'altra transazione (in cui l'altra transazione avviene dopo l'istantanea del primo, ma si impegna per prima), mentre l'altra transazione continua a utilizzare dati non aggiornati e prende qualsiasi decisione in modo diverso sulla base di quei dati obsoleti rispetto a ciò che avrebbe fatto dati aggiornati. È più facile da causare di quanto si pensi.
La coerenza rilassata è un altro modo di dire potenzialmente incoerente o soggetto a errori. (La coerenza rilassata non deve essere confusa con l'eventuale coerenza, che è un'altra forma popolare diversa di errore soggetta a "NoSQL".)
Alla tua domanda, quando dici che le transazioni non devono mai estendersi a più di un oggetto, questo deve valere sia per le letture e le scritture, sia per i metadati (e le meta-operazioni), inclusi controllo di coerenza, aggregati di colonne intere, controlli di assenza, ricerche di intervallo, ecc. .: se è così, allora finora tutto bene.
Tuttavia...
Prendo dalla tua domanda che stai usando l'isolamento di istantanee (MVCC) su singoli oggetti (diciamo piuttosto che il blocco degli oggetti). (Parli anche di CAS; ho sentito parlare di confronta-e-scambia e, test-and-set, ma non check-and-set, anche se presumo che sia simile).
La tua domanda scritta mi suggerisce che gli "oggetti" hanno più di un campo, altrimenti le clausole della domanda non sarebbero necessarie.
Pertanto, poiché gli oggetti gestiti dallo snapshot / gestiti da MVCC hanno più di un campo, si è inclini a scrivere inclinazioni all'interno di singoli oggetti. Se due transazioni aggiornano lo stesso oggetto contemporaneamente, è possibile leggere un campo del valore dell'oggetto reso obsoleto da un'altra transazione simultanea sullo stesso oggetto e continuare senza conoscere, quindi, potenziali incoerenze (ovvero errori).
È possibile utilizzare invece il blocco degli oggetti, che impedirebbe a due transazioni (per l'aggiornamento) di guardare lo stesso oggetto anche se un'altra transazione fosse già in procinto di farlo.
Credo che una forma alternativa di isolamento dello snapshot possa essere eseguita senza utilizzare il modello di confronto del solo set di scrittura rotto di MVCC. Quindi, puoi (algoritmicamente) promuovere il set di confronto da sola scrittura per includere anche il set di lettura. Quindi due transazioni che aggiornano lo stesso oggetto non sarebbero in grado di causare l'inclinazione della scrittura (perché quella che tenta di eseguire il commit in seguito verrebbe interrotta). Penso che questa potrebbe essere la soluzione appropriata al problema che stai descrivendo, perché stai già ottenendo la maggior parte del vantaggio che MVCC ci acquisterebbe, precludendo le transazioni multi-oggetto.
(Dobbiamo solo considerare gli articoli / campi esatti e specifici letti o scritti, ma dobbiamo includere quelli letti come metadati, potenzialmente durante le meta-operazioni per prevenire l'inclinazione della scrittura (es. Errore). Se rimuoviamo il set letto dal set di confronto o non consideriamo i metadati (potenzialmente utilizzati dalle meta operazioni), quindi abbiamo un modello che consentirà l'errore.)